< prev index next >

src/hotspot/share/classfile/systemDictionary.cpp

Print this page
*** 53,10 ***
--- 53,11 ---
  #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"

*** 64,18 ***
--- 65,20 ---
  #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/atomic.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"

*** 186,17 ***
  // Helper function
  inline ClassLoaderData* class_loader_data(Handle class_loader) {
    return ClassLoaderData::class_loader_data(class_loader());
  }
  
  ClassLoaderData* SystemDictionary::register_loader(Handle class_loader, bool create_mirror_cld) {
    if (create_mirror_cld) {
      // Add a new class loader data to the graph.
      return ClassLoaderDataGraph::add(class_loader, true);
    } else {
!     return (class_loader() == nullptr) ? ClassLoaderData::the_null_class_loader_data() :
!                                       ClassLoaderDataGraph::find_or_create(class_loader);
    }
  }
  
  void SystemDictionary::set_system_loader(ClassLoaderData *cld) {
    assert(_java_system_loader.is_empty(), "already set!");
--- 189,41 ---
  // Helper function
  inline ClassLoaderData* class_loader_data(Handle class_loader) {
    return ClassLoaderData::class_loader_data(class_loader());
  }
  
+ static void add_wrapper_class(JavaThread* current, ClassLoaderData* cld, Symbol* classname) {
+   InstanceKlass* ik = SystemDictionary::find_instance_klass(current, classname, Handle(current, nullptr));
+   assert(ik != nullptr, "Must exist");
+   SystemDictionary::add_to_initiating_loader(current, ik, cld);
+ }
+ 
+ static void add_wrapper_classes(ClassLoaderData* cld) {
+   MonitorLocker mu1(SystemDictionary_lock);
+   JavaThread* current = JavaThread::current();
+   add_wrapper_class(current, cld, vmSymbols::java_lang_Boolean());
+   add_wrapper_class(current, cld, vmSymbols::java_lang_Byte());
+   add_wrapper_class(current, cld, vmSymbols::java_lang_Character());
+   add_wrapper_class(current, cld, vmSymbols::java_lang_Short());
+   add_wrapper_class(current, cld, vmSymbols::java_lang_Integer());
+   add_wrapper_class(current, cld, vmSymbols::java_lang_Long());
+   add_wrapper_class(current, cld, vmSymbols::java_lang_Float());
+   add_wrapper_class(current, cld, vmSymbols::java_lang_Double());
+ }
+ 
  ClassLoaderData* SystemDictionary::register_loader(Handle class_loader, bool create_mirror_cld) {
    if (create_mirror_cld) {
      // Add a new class loader data to the graph.
      return ClassLoaderDataGraph::add(class_loader, true);
    } else {
!     if (class_loader() == nullptr) {
!       return ClassLoaderData::the_null_class_loader_data();
+     } else {
+       ClassLoaderData* cld = ClassLoaderDataGraph::find_or_create(class_loader);
+       add_wrapper_classes(cld);
+       return cld;
+     }
    }
  }
  
  void SystemDictionary::set_system_loader(ClassLoaderData *cld) {
    assert(_java_system_loader.is_empty(), "already set!");

*** 347,11 ***
      return resolve_array_class_or_null(class_name, class_loader, 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, THREAD);
      } else {
        return resolve_instance_class_or_null(class_name, class_loader, THREAD);
--- 374,11 ---
      return resolve_array_class_or_null(class_name, class_loader, 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, THREAD);
      } else {
        return resolve_instance_class_or_null(class_name, class_loader, THREAD);

*** 916,12 ***
  // Check if a shared class can be loaded by the specific classloader.
  bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
                                                 InstanceKlass* ik,
                                                 PackageEntry* pkg_entry,
                                                 Handle class_loader) {
!   assert(!ModuleEntryTable::javabase_moduleEntry()->is_patched(),
-          "Cannot use sharing if java.base is patched");
  
    // (1) Check if we are loading into the same loader as in dump time.
  
    if (ik->is_shared_boot_class()) {
      if (class_loader() != nullptr) {
--- 943,11 ---
  // Check if a shared class can be loaded by the specific classloader.
  bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
                                                 InstanceKlass* ik,
                                                 PackageEntry* pkg_entry,
                                                 Handle class_loader) {
!   assert(!CDSConfig::module_patching_disables_cds(), "Cannot use CDS");
  
    // (1) Check if we are loading into the same loader as in dump time.
  
    if (ik->is_shared_boot_class()) {
      if (class_loader() != nullptr) {

*** 993,11 ***
    if (was_archived_from_named_module) {
      if (should_be_in_named_module) {
        // Is the module loaded from the same location as during dump time?
        visible = mod_entry->shared_path_index() == scp_index;
        if (visible) {
!         assert(!mod_entry->is_patched(), "cannot load archived classes for patched module");
        }
      } else {
        // During dump time, this class was in a named module, but at run time, this class should be
        // in an unnamed module.
        visible = false;
--- 1019,11 ---
    if (was_archived_from_named_module) {
      if (should_be_in_named_module) {
        // Is the module loaded from the same location as during dump time?
        visible = mod_entry->shared_path_index() == scp_index;
        if (visible) {
!         assert(!CDSConfig::module_patching_disables_cds(), "Cannot use CDS");
        }
      } else {
        // During dump time, this class was in a named module, but at run time, this class should be
        // in an unnamed module.
        visible = false;

*** 1071,10 ***
--- 1097,79 ---
    }
  
    return true;
  }
  
+ // Pre-load class referred to in non-static null-free instance field. These fields trigger MANDATORY loading.
+ // Some pre-loading does not fail fatally
+ bool SystemDictionary::preload_from_null_free_field(InstanceKlass* ik, Handle class_loader, Symbol* sig, int field_index, TRAPS) {
+   TempNewSymbol name = Signature::strip_envelope(sig);
+   log_info(class, preload)("Preloading class %s during loading of shared class %s. "
+                            "Cause: a null-free non-static field is declared with this type",
+                            name->as_C_string(), ik->name()->as_C_string());
+   InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection_or_fail(ik->name(), name,
+                                                                                class_loader, false, CHECK_false);
+   if (HAS_PENDING_EXCEPTION) {
+     log_warning(class, preload)("Preloading of class %s during loading of class %s "
+                                 "(cause: null-free non-static field) failed: %s",
+                                 name->as_C_string(), ik->name()->as_C_string(),
+                                 PENDING_EXCEPTION->klass()->name()->as_C_string());
+     return false; // Exception is still pending
+   }
+ 
+   InstanceKlass* k = ik->get_inline_type_field_klass_or_null(field_index);
+   if (real_k != k) {
+     // oops, the app has substituted a different version of k! Does not fail fatally
+     log_warning(class, preload)("Preloading of class %s during loading of shared class %s "
+                                 "(cause: null-free non-static field) failed : "
+                                 "app substituted a different version of %s",
+                                 name->as_C_string(), ik->name()->as_C_string(),
+                                 name->as_C_string());
+     return false;
+   }
+   log_info(class, preload)("Preloading of class %s during loading of shared class %s "
+                            "(cause: null-free non-static field) succeeded",
+                            name->as_C_string(), ik->name()->as_C_string());
+ 
+   assert(real_k != nullptr, "Sanity check");
+   InstanceKlass::check_can_be_annotated_with_NullRestricted(real_k, ik->name(), CHECK_false);
+ 
+   return true;
+ }
+ 
+ // Tries to pre-load classes referred to in non-static nullable instance fields if they are found in the
+ // loadable descriptors attribute. If loading fails, we can fail silently.
+ void SystemDictionary::try_preload_from_loadable_descriptors(InstanceKlass* ik, Handle class_loader, Symbol* sig, int field_index, TRAPS) {
+   TempNewSymbol name = Signature::strip_envelope(sig);
+   if (name != ik->name() && ik->is_class_in_loadable_descriptors_attribute(sig)) {
+     log_info(class, preload)("Preloading class %s during loading of shared class %s. "
+                              "Cause: field type in LoadableDescriptors attribute",
+                              name->as_C_string(), ik->name()->as_C_string());
+     InstanceKlass* real_k = SystemDictionary::resolve_with_circularity_detection_or_fail(ik->name(), name,
+                                                                                  class_loader, false, THREAD);
+     if (HAS_PENDING_EXCEPTION) {
+       CLEAR_PENDING_EXCEPTION;
+     }
+ 
+     InstanceKlass* k = ik->get_inline_type_field_klass_or_null(field_index);
+     if (real_k != k) {
+       // oops, the app has substituted a different version of k!
+       log_warning(class, preload)("Preloading of class %s during loading of shared class %s "
+                                   "(cause: field type in LoadableDescriptors attribute) failed : "
+                                   "app substituted a different version of %s",
+                                   name->as_C_string(), ik->name()->as_C_string(),
+                                   k->name()->as_C_string());
+       return;
+     } else if (real_k != nullptr) {
+       log_info(class, preload)("Preloading of class %s during loading of shared class %s "
+                                "(cause: field type in LoadableDescriptors attribute) succeeded",
+                                 name->as_C_string(), ik->name()->as_C_string());
+     }
+   }
+ }
+ 
+ 
  InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
                                                     Handle class_loader,
                                                     Handle protection_domain,
                                                     const ClassFileStream *cfs,
                                                     PackageEntry* pkg_entry,

*** 1094,10 ***
--- 1189,31 ---
    if (!check) {
      ik->set_shared_loading_failed();
      return nullptr;
    }
  
+   if (ik->has_inline_type_fields()) {
+     for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
+       if (fs.access_flags().is_static()) continue;
+ 
+       Symbol* sig = fs.signature();
+       int field_index = fs.index();
+ 
+       if (fs.is_null_free_inline_type()) {
+         // A false return means that the class didn't load for other reasons than an exception.
+         bool check = preload_from_null_free_field(ik, class_loader, sig, field_index, CHECK_NULL);
+         if (!check) {
+           ik->set_shared_loading_failed();
+           return nullptr;
+         }
+       } else if (Signature::has_envelope(sig)) {
+           // Pending exceptions are cleared so we can fail silently
+           try_preload_from_loadable_descriptors(ik, class_loader, sig, field_index, CHECK_NULL);
+       }
+     }
+   }
+ 
    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 (!ik->is_hidden()) {
      new_ik = KlassFactory::check_shared_class_file_load_hook(

*** 1129,10 ***
--- 1245,11 ---
      // 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);

*** 1651,27 ***
      dictionary->add_klass(current, name, k);
    }
    mu1.notify_all();
  }
  
- #if INCLUDE_CDS
  // Indicate that loader_data has initiated the loading of class k, which
  // has already been defined by a parent loader.
! // This API should be used only by AOTLinkedClassBulkLoader
  void SystemDictionary::add_to_initiating_loader(JavaThread* current,
                                                  InstanceKlass* k,
                                                  ClassLoaderData* loader_data) {
-   assert(CDSConfig::is_using_aot_linked_classes(), "must be");
    assert_locked_or_safepoint(SystemDictionary_lock);
    Symbol* name  = k->name();
    Dictionary* dictionary = loader_data->dictionary();
    assert(k->is_loaded(), "must be");
    assert(k->class_loader_data() != loader_data, "only for classes defined by a parent loader");
!   assert(dictionary->find_class(current, name) == nullptr, "sanity");
!   dictionary->add_klass(current, name, k);
  }
- #endif
  
  // Try to find a class name using the loader constraints.  The
  // loader constraints might know about a class that isn't fully loaded
  // yet and these will be ignored.
  Klass* SystemDictionary::find_constrained_instance_or_array_klass(
--- 1768,27 ---
      dictionary->add_klass(current, name, k);
    }
    mu1.notify_all();
  }
  
  // Indicate that loader_data has initiated the loading of class k, which
  // has already been defined by a parent loader.
! // This API is used by AOTLinkedClassBulkLoader and to register boxing
+ // classes from java.lang in all class loaders to enable more value
+ // classes optimizations
  void SystemDictionary::add_to_initiating_loader(JavaThread* current,
                                                  InstanceKlass* k,
                                                  ClassLoaderData* loader_data) {
    assert_locked_or_safepoint(SystemDictionary_lock);
    Symbol* name  = k->name();
    Dictionary* dictionary = loader_data->dictionary();
    assert(k->is_loaded(), "must be");
    assert(k->class_loader_data() != loader_data, "only for classes defined by a parent loader");
!   if (dictionary->find_class(current, name) == nullptr) {
!     dictionary->add_klass(current, name, k);
+   }
  }
  
  // Try to find a class name using the loader constraints.  The
  // loader constraints might know about a class that isn't fully loaded
  // yet and these will be ignored.
  Klass* SystemDictionary::find_constrained_instance_or_array_klass(
< prev index next >