< prev index next > src/hotspot/share/classfile/systemDictionaryShared.cpp
Print this page
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/compressedKlass.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
+ #include "oops/methodData.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oopHandle.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
SystemDictionaryShared::ArchiveInfo SystemDictionaryShared::_static_archive;
SystemDictionaryShared::ArchiveInfo SystemDictionaryShared::_dynamic_archive;
DumpTimeSharedClassTable* SystemDictionaryShared::_dumptime_table = nullptr;
+ bool SystemDictionaryShared::_finished_exclusion_checks = false;
// Used by NoClassLoadingMark
DEBUG_ONLY(bool SystemDictionaryShared::_class_loading_may_happen = true;)
#ifdef ASSERT
if (ik != nullptr && !ik->shared_loading_failed()) {
if ((SystemDictionary::is_system_class_loader(class_loader()) && ik->defined_by_app_loader()) ||
(SystemDictionary::is_platform_class_loader(class_loader()) && ik->defined_by_platform_loader())) {
SharedClassLoadingMark slm(THREAD, ik);
PackageEntry* pkg_entry = CDSProtectionDomain::get_package_entry_from_class(ik, class_loader);
- Handle protection_domain =
- CDSProtectionDomain::init_security_info(class_loader, ik, pkg_entry, CHECK_NULL);
+ Handle protection_domain;
+ if (!class_name->starts_with("jdk/proxy")) // java/lang/reflect/Proxy$ProxyBuilder defines the proxy classes with a null protection domain.
+ {
+ protection_domain = CDSProtectionDomain::init_security_info(class_loader, ik, pkg_entry, CHECK_NULL);
+ }
return load_shared_class(ik, class_loader, protection_domain, nullptr, pkg_entry, THREAD);
}
}
return nullptr;
}
// Returns true if the class should be excluded. This can be called by
// AOTConstantPoolResolver before or after we enter the CDS safepoint.
// When called before the safepoint, we need to link the class so that
// it can be checked by should_be_excluded_impl().
bool SystemDictionaryShared::should_be_excluded(Klass* k) {
- assert(CDSConfig::is_dumping_archive(), "sanity");
- assert(CDSConfig::current_thread_is_vm_or_dumper(), "sanity");
-
if (CDSConfig::is_dumping_dynamic_archive() && AOTMetaspace::in_aot_cache(k)) {
// We have reached a super type that's already in the base archive. Treat it
// as "not excluded".
return false;
}
assert(k->is_typeArray_klass(), "must be");
return false;
} else {
InstanceKlass* ik = InstanceKlass::cast(k);
+ if (CDSConfig::is_dumping_final_static_archive() && _finished_exclusion_checks &&
+ !SafepointSynchronize::is_at_safepoint()) {
+ // This is called from the AOT compiler.
+ MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
+ DumpTimeClassInfo* p = get_info_locked(ik);
+ if (p->is_excluded()) {
+ return true;
+ } else if (!p->has_checked_exclusion()) {
+ // This is a class that was loaded after we exited the AOT safepoint. This
+ // class is not in the AOT cache, so it must be considered as "excluded"
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ assert(CDSConfig::is_dumping_archive(), "sanity");
+ assert(CDSConfig::current_thread_is_vm_or_dumper(), "sanity");
+
if (!SafepointSynchronize::is_at_safepoint()) {
if (!ik->is_linked()) {
// should_be_excluded_impl() below doesn't link unlinked classes. We come
// here only when we are trying to aot-link constant pool entries, so
// we'd better link the class.
_dumptime_table->update_counts();
if (CDSConfig::is_dumping_lambdas_in_legacy_mode()) {
LambdaProxyClassDictionary::cleanup_dumptime_table();
}
+ _finished_exclusion_checks = true;
}
bool SystemDictionaryShared::is_excluded_class(InstanceKlass* k) {
assert(!class_loading_may_happen(), "class loading must be disabled");
assert_lock_strong(DumpTimeTable_lock);
// false: is_reference_assignable_from() should COMPLETE the assignability check
void SystemDictionaryShared::add_verification_constraint(InstanceKlass* k, Symbol* name,
Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object,
bool* skip_assignability_check) {
assert(CDSConfig::is_dumping_archive(), "sanity");
+ if (CDSConfig::is_dumping_dynamic_archive() && k->in_aot_cache()) {
+ // k is a new class in the static archive, but one of its supertypes is an old class, so k wasn't
+ // verified during dump time. No need to record constraints as k won't be included in the dynamic archive.
+ return;
+ }
+ if (CDSConfig::is_dumping_aot_linked_classes() && is_builtin(k)) {
+ // There's no need to save verification constraints
+ // TODO -- double check the logic before integrating into mainline!!
+ return;
+ }
+
DumpTimeClassInfo* info = get_info(k);
info->add_verification_constraint(name, from_name, from_field_is_protected,
from_is_array, from_is_object);
if (CDSConfig::is_dumping_classic_static_archive() && !is_builtin(k)) {
if (_dumptime_table->count_of(true) == 0 && _dumptime_table->count_of(false) == 0){
return true;
}
return false;
}
+
+ void SystemDictionaryShared::create_loader_positive_lookup_cache(TRAPS) {
+ GrowableArray<InstanceKlass*> shared_classes_list;
+ {
+ // With static dumping, we have only a single Java thread (see JVM_StartThread) so
+ // no no other threads should be loading classes. Otherwise, the code below may miss some
+ // classes that are loaded concurrently.
+ assert(CDSConfig::is_dumping_static_archive(), "no other threads should be loading classes");
+
+ MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
+ _dumptime_table->iterate_all_classes_in_builtin_loaders([&](InstanceKlass* k, DumpTimeClassInfo& info) {
+ // FIXME -- this may not be correct before SystemDictionaryShared::finish_exclusion_checks()
+ if (!k->is_hidden() && info.has_checked_exclusion() && !info.is_excluded()) {
+ shared_classes_list.append(k);
+ }
+ }
+ );
+ }
+
+ InstanceKlass* ik = vmClasses::Class_klass();
+ objArrayOop r = oopFactory::new_objArray(ik, shared_classes_list.length(), CHECK);
+ objArrayHandle array_h(THREAD, r);
+
+ for (int i = 0; i < shared_classes_list.length(); i++) {
+ oop mirror = shared_classes_list.at(i)->java_mirror();
+ Handle mirror_h(THREAD, mirror);
+ array_h->obj_at_put(i, mirror_h());
+ }
+
+ TempNewSymbol method = SymbolTable::new_symbol("generatePositiveLookupCache");
+ TempNewSymbol signature = SymbolTable::new_symbol("([Ljava/lang/Class;)V");
+
+ JavaCallArguments args(Handle(THREAD, SystemDictionary::java_system_loader()));
+ args.push_oop(array_h);
+ JavaValue result(T_VOID);
+ JavaCalls::call_virtual(&result,
+ vmClasses::jdk_internal_loader_ClassLoaders_AppClassLoader_klass(),
+ method,
+ signature,
+ &args,
+ CHECK);
+
+ if (HAS_PENDING_EXCEPTION) {
+ Handle exc_handle(THREAD, PENDING_EXCEPTION);
+ CLEAR_PENDING_EXCEPTION;
+ ResourceMark rm(THREAD);
+
+ log_warning(cds)("Exception during AppClassLoader::generatePositiveLookupCache() call");
+ LogStreamHandle(Debug, cds) log;
+ if (log.is_enabled()) {
+ java_lang_Throwable::print_stack_trace(exc_handle, &log);
+ }
+ return;
+ }
+ }
< prev index next >