< prev index next > src/hotspot/share/classfile/systemDictionary.cpp
Print this page
#include "memory/metaspaceClosure.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
+ #include "oops/fieldStreams.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.hpp"
#include "oops/oopHandle.hpp"
#include "oops/oopHandle.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
+ #include "oops/inlineKlass.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
+ #include "runtime/os.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/signature.hpp"
#include "runtime/synchronizer.hpp"
#include "services/classLoadingService.hpp"
#include "services/diagnosticCommand.hpp"
return resolve_array_class_or_null(class_name, class_loader, protection_domain, THREAD);
} else {
assert(class_name != nullptr && !Signature::is_array(class_name), "must be");
if (Signature::has_envelope(class_name)) {
ResourceMark rm(THREAD);
! // Ignore wrapping L and ;.
TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1,
class_name->utf8_length() - 2);
return resolve_instance_class_or_null(name, class_loader, protection_domain, THREAD);
} else {
return resolve_instance_class_or_null(class_name, class_loader, protection_domain, THREAD);
return resolve_array_class_or_null(class_name, class_loader, protection_domain, THREAD);
} else {
assert(class_name != nullptr && !Signature::is_array(class_name), "must be");
if (Signature::has_envelope(class_name)) {
ResourceMark rm(THREAD);
! // Ignore wrapping L and ; (and Q and ; for value types).
TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1,
class_name->utf8_length() - 2);
return resolve_instance_class_or_null(name, class_loader, protection_domain, THREAD);
} else {
return resolve_instance_class_or_null(class_name, class_loader, protection_domain, THREAD);
k = SystemDictionary::resolve_instance_class_or_null(obj_class,
class_loader,
protection_domain,
CHECK_NULL);
if (k != nullptr) {
! k = k->array_klass(ndims, CHECK_NULL);
}
} else {
k = Universe::typeArrayKlassObj(t);
k = TypeArrayKlass::cast(k)->array_klass(ndims, CHECK_NULL);
}
k = SystemDictionary::resolve_instance_class_or_null(obj_class,
class_loader,
protection_domain,
CHECK_NULL);
if (k != nullptr) {
! if (class_name->is_Q_array_signature()) {
+ if (!k->is_inline_klass()) {
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), "L/Q mismatch on bottom type");
+ }
+ k = InlineKlass::cast(k)->value_array_klass(ndims, CHECK_NULL);
+ } else {
+ k = k->array_klass(ndims, CHECK_NULL);
+ }
}
} else {
k = Universe::typeArrayKlassObj(t);
k = TypeArrayKlass::cast(k)->array_klass(ndims, CHECK_NULL);
}
}
return superk;
}
+ Klass* SystemDictionary::resolve_inline_type_field_or_fail(Symbol* signature,
+ Handle class_loader,
+ Handle protection_domain,
+ bool throw_error,
+ TRAPS) {
+ Symbol* class_name = signature->fundamental_name(THREAD);
+ class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
+ ClassLoaderData* loader_data = class_loader_data(class_loader);
+ bool throw_circularity_error = false;
+ PlaceholderEntry* oldprobe;
+
+ {
+ MutexLocker mu(THREAD, SystemDictionary_lock);
+ oldprobe = PlaceholderTable::get_entry(class_name, loader_data);
+ if (oldprobe != nullptr &&
+ oldprobe->check_seen_thread(THREAD, PlaceholderTable::PRIMITIVE_OBJECT_FIELD)) {
+ throw_circularity_error = true;
+
+ } else {
+ PlaceholderTable::find_and_add(class_name, loader_data,
+ PlaceholderTable::PRIMITIVE_OBJECT_FIELD, nullptr, THREAD);
+ }
+ }
+
+ Klass* klass = nullptr;
+ if (!throw_circularity_error) {
+ klass = SystemDictionary::resolve_or_fail(class_name, class_loader,
+ protection_domain, true, THREAD);
+ } else {
+ ResourceMark rm(THREAD);
+ THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), class_name->as_C_string());
+ }
+
+ {
+ MutexLocker mu(THREAD, SystemDictionary_lock);
+ PlaceholderTable::find_and_remove(class_name, loader_data,
+ PlaceholderTable::PRIMITIVE_OBJECT_FIELD, THREAD);
+ }
+
+ class_name->decrement_refcount();
+ return klass;
+ }
+
// If the class in is in the placeholder table, class loading is in progress.
// For cases where the application changes threads to load classes, it
// is critical to ClassCircularity detection that we try loading
// the superclass on the new thread internally, so we do parallel
// superclass loading here. This avoids deadlock for ClassCircularity
Handle class_loader,
Handle protection_domain,
TRAPS) {
// name must be in the form of "java/lang/Object" -- cannot be "Ljava/lang/Object;"
assert(name != nullptr && !Signature::is_array(name) &&
! !Signature::has_envelope(name), "invalid class name");
EventClassLoad class_load_start_event;
HandleMark hm(THREAD);
Handle class_loader,
Handle protection_domain,
TRAPS) {
// name must be in the form of "java/lang/Object" -- cannot be "Ljava/lang/Object;"
assert(name != nullptr && !Signature::is_array(name) &&
! !Signature::has_envelope(name), "invalid class name: %s", name == nullptr ? "nullptr" : name->as_C_string());
EventClassLoad class_load_start_event;
HandleMark hm(THREAD);
// dimension and object_key in FieldArrayInfo are assigned as a
// side-effect of this call
SignatureStream ss(class_name, false);
int ndims = ss.skip_array_prefix(); // skip all '['s
BasicType t = ss.type();
! if (t != T_OBJECT) {
k = Universe::typeArrayKlassObj(t);
} else {
k = SystemDictionary::find_instance_klass(current, ss.as_symbol(), class_loader, protection_domain);
}
if (k != nullptr) {
! k = k->array_klass_or_null(ndims);
}
} else {
k = find_instance_klass(current, class_name, class_loader, protection_domain);
}
return k;
// dimension and object_key in FieldArrayInfo are assigned as a
// side-effect of this call
SignatureStream ss(class_name, false);
int ndims = ss.skip_array_prefix(); // skip all '['s
BasicType t = ss.type();
! if (t != T_OBJECT && t != T_PRIMITIVE_OBJECT) {
k = Universe::typeArrayKlassObj(t);
} else {
k = SystemDictionary::find_instance_klass(current, ss.as_symbol(), class_loader, protection_domain);
}
if (k != nullptr) {
! if (class_name->is_Q_array_signature()) {
+ k = InlineKlass::cast(k)->value_array_klass_or_null(ndims);
+ } else {
+ k = k->array_klass_or_null(ndims);
+ }
}
} else {
k = find_instance_klass(current, class_name, class_loader, protection_domain);
}
return k;
if (!check_shared_class_super_types(ik, class_loader, protection_domain, THREAD)) {
return nullptr;
}
+
+ if (ik->has_inline_type_fields()) {
+ for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
+ Symbol* sig = fs.signature();
+ if (Signature::basic_type(sig) == T_PRIMITIVE_OBJECT) {
+ if (!fs.access_flags().is_static()) {
+ // Pre-load inline class
+ Klass* real_k = SystemDictionary::resolve_inline_type_field_or_fail(sig,
+ class_loader, protection_domain, true, CHECK_NULL);
+ Klass* k = ik->get_inline_type_field_klass_or_null(fs.index());
+ if (real_k != k) {
+ // oops, the app has substituted a different version of k!
+ return nullptr;
+ }
+ }
+ }
+ }
+ }
+
InstanceKlass* new_ik = nullptr;
// CFLH check is skipped for VM hidden classes (see KlassFactory::create_from_stream).
// It will be skipped for shared VM hidden lambda proxy classes.
if (!SystemDictionaryShared::is_hidden_lambda_proxy(ik)) {
new_ik = KlassFactory::check_shared_class_file_load_hook(
// restore_unshareable_info which calls ik->set_package()
ik->restore_unshareable_info(loader_data, protection_domain, pkg_entry, CHECK_NULL);
}
load_shared_class_misc(ik, loader_data);
+
return ik;
}
void SystemDictionary::load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data) {
ik->print_class_load_logging(loader_data, nullptr, nullptr);
// For array classes, their Klass*s are not kept in the
// constraint table. The element Klass*s are.
SignatureStream ss(class_name, false);
int ndims = ss.skip_array_prefix(); // skip all '['s
BasicType t = ss.type();
! if (t != T_OBJECT) {
klass = Universe::typeArrayKlassObj(t);
} else {
MutexLocker mu(current, SystemDictionary_lock);
klass = LoaderConstraintTable::find_constrained_klass(ss.as_symbol(), class_loader_data(class_loader));
}
// If element class already loaded, allocate array klass
if (klass != nullptr) {
! klass = klass->array_klass_or_null(ndims);
}
} else {
MutexLocker mu(current, SystemDictionary_lock);
// Non-array classes are easy: simply check the constraint table.
klass = LoaderConstraintTable::find_constrained_klass(class_name, class_loader_data(class_loader));
// For array classes, their Klass*s are not kept in the
// constraint table. The element Klass*s are.
SignatureStream ss(class_name, false);
int ndims = ss.skip_array_prefix(); // skip all '['s
BasicType t = ss.type();
! if (t != T_OBJECT && t != T_PRIMITIVE_OBJECT) {
klass = Universe::typeArrayKlassObj(t);
} else {
MutexLocker mu(current, SystemDictionary_lock);
klass = LoaderConstraintTable::find_constrained_klass(ss.as_symbol(), class_loader_data(class_loader));
}
// If element class already loaded, allocate array klass
if (klass != nullptr) {
! if (class_name->is_Q_array_signature()) {
+ klass = InlineKlass::cast(klass)->value_array_klass_or_null(ndims);
+ } else {
+ klass = klass->array_klass_or_null(ndims);
+ }
}
} else {
MutexLocker mu(current, SystemDictionary_lock);
// Non-array classes are easy: simply check the constraint table.
klass = LoaderConstraintTable::find_constrained_klass(class_name, class_loader_data(class_loader));
< prev index next >