< prev index next >

src/hotspot/share/classfile/systemDictionaryShared.cpp

Print this page
@@ -63,10 +63,11 @@
  #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"

@@ -80,10 +81,11 @@
  
  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

@@ -104,12 +106,15 @@
    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;
  }

@@ -848,13 +853,10 @@
  // 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;
    }

@@ -865,10 +867,29 @@
      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.

@@ -929,10 +950,11 @@
  
    _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);

@@ -1001,10 +1023,21 @@
  //     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)) {

@@ -1483,5 +1516,60 @@
    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 >