Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


SSL systemDictionary.cpp   Interaktion und
PortierbarkeitC

 
/*
 * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


#include "precompiled.hpp"
#include "cds/heapShared.hpp"
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/classLoadInfo.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/klassFactory.hpp"
#include "classfile/loaderConstraints.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/placeholders.hpp"
#include "classfile/protectionDomainCache.hpp"
#include "classfile/resolutionErrors.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmClasses.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "interpreter/bootstrapInfo.hpp"
#include "jfr/jfrEvents.hpp"
#include "jvm.h"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/access.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.inline.hpp"
#include "oops/oop.hpp"
#include "oops/oopHandle.hpp"
#include "oops/oopHandle.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.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/sharedRuntime.hpp"
#include "runtime/signature.hpp"
#include "runtime/synchronizer.hpp"
#include "services/classLoadingService.hpp"
#include "services/diagnosticCommand.hpp"
#include "services/finalizerService.hpp"
#include "services/threadService.hpp"
#include "utilities/macros.hpp"
#include "utilities/utf8.hpp"
#if INCLUDE_CDS
#include "classfile/systemDictionaryShared.hpp"
#endif
#if INCLUDE_JFR
#include "jfr/jfr.hpp"
#endif

class InvokeMethodKey : public StackObj {
  private:
    Symbol* _symbol;
    intptr_t _iid;

  public:
    InvokeMethodKey(Symbol* symbol, intptr_t iid) :
        _symbol(symbol),
        _iid(iid) {}

    static bool key_comparison(InvokeMethodKey const &k1, InvokeMethodKey const &k2){
        return k1._symbol == k2._symbol && k1._iid == k2._iid;
    }

    static unsigned int compute_hash(const InvokeMethodKey &k) {
        Symbol* sym = k._symbol;
        intptr_t iid = k._iid;
        unsigned int hash = (unsigned int) sym -> identity_hash();
        return (unsigned int) (hash ^ iid);
    }

};

ResourceHashtable<InvokeMethodKey, Method*, 139, AnyObj::C_HEAP, mtClass,
                  InvokeMethodKey::compute_hash, InvokeMethodKey::key_comparison> _invoke_method_intrinsic_table;
ResourceHashtable<SymbolHandle, OopHandle, 139, AnyObj::C_HEAP, mtClass, SymbolHandle::compute_hash> _invoke_method_type_table;

OopHandle   SystemDictionary::_java_system_loader;
OopHandle   SystemDictionary::_java_platform_loader;

// ----------------------------------------------------------------------------
// Java-level SystemLoader and PlatformLoader
oop SystemDictionary::java_system_loader() {
  return _java_system_loader.resolve();
}

oop SystemDictionary::java_platform_loader() {
  return _java_platform_loader.resolve();
}

void SystemDictionary::compute_java_loaders(TRAPS) {
  if (_java_system_loader.is_empty()) {
    oop system_loader = get_system_class_loader_impl(CHECK);
    _java_system_loader = OopHandle(Universe::vm_global(), system_loader);
  } else {
    // It must have been restored from the archived module graph
    assert(UseSharedSpaces, "must be");
    assert(MetaspaceShared::use_full_module_graph(), "must be");
    DEBUG_ONLY(
      oop system_loader = get_system_class_loader_impl(CHECK);
      assert(_java_system_loader.resolve() == system_loader, "must be");
    )
 }

  if (_java_platform_loader.is_empty()) {
    oop platform_loader = get_platform_class_loader_impl(CHECK);
    _java_platform_loader = OopHandle(Universe::vm_global(), platform_loader);
  } else {
    // It must have been restored from the archived module graph
    assert(UseSharedSpaces, "must be");
    assert(MetaspaceShared::use_full_module_graph(), "must be");
    DEBUG_ONLY(
      oop platform_loader = get_platform_class_loader_impl(CHECK);
      assert(_java_platform_loader.resolve() == platform_loader, "must be");
    )
  }
}

oop SystemDictionary::get_system_class_loader_impl(TRAPS) {
  JavaValue result(T_OBJECT);
  InstanceKlass* class_loader_klass = vmClasses::ClassLoader_klass();
  JavaCalls::call_static(&result,
                         class_loader_klass,
                         vmSymbols::getSystemClassLoader_name(),
                         vmSymbols::void_classloader_signature(),
                         CHECK_NULL);
  return result.get_oop();
}

oop SystemDictionary::get_platform_class_loader_impl(TRAPS) {
  JavaValue result(T_OBJECT);
  InstanceKlass* class_loader_klass = vmClasses::ClassLoader_klass();
  JavaCalls::call_static(&result,
                         class_loader_klass,
                         vmSymbols::getPlatformClassLoader_name(),
                         vmSymbols::void_classloader_signature(),
                         CHECK_NULL);
  return result.get_oop();
}

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() == NULL) ? 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!");
  _java_system_loader = cld->class_loader_handle();

}

void SystemDictionary::set_platform_loader(ClassLoaderData *cld) {
  assert(_java_platform_loader.is_empty(), "already set!");
  _java_platform_loader = cld->class_loader_handle();
}

// ----------------------------------------------------------------------------
// Parallel class loading check

bool is_parallelCapable(Handle class_loader) {
  if (class_loader.is_null()) return true;
  return java_lang_ClassLoader::parallelCapable(class_loader());
}
// ----------------------------------------------------------------------------
// ParallelDefineClass flag does not apply to bootclass loader
bool is_parallelDefine(Handle class_loader) {
   if (class_loader.is_null()) return false;
   if (AllowParallelDefineClass && java_lang_ClassLoader::parallelCapable(class_loader())) {
     return true;
   }
   return false;
}

// Returns true if the passed class loader is the builtin application class loader
// or a custom system class loader. A customer system class loader can be
// specified via -Djava.system.class.loader.
bool SystemDictionary::is_system_class_loader(oop class_loader) {
  if (class_loader == NULL) {
    return false;
  }
  return (class_loader->klass() == vmClasses::jdk_internal_loader_ClassLoaders_AppClassLoader_klass() ||
         class_loader == _java_system_loader.peek());
}

// Returns true if the passed class loader is the platform class loader.
bool SystemDictionary::is_platform_class_loader(oop class_loader) {
  if (class_loader == NULL) {
    return false;
  }
  return (class_loader->klass() == vmClasses::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass());
}

Handle SystemDictionary::get_loader_lock_or_null(Handle class_loader) {
  // If class_loader is NULL or parallelCapable, the JVM doesn't acquire a lock while loading.
  if (is_parallelCapable(class_loader)) {
    return Handle();
  } else {
    return class_loader;
  }
}

// ----------------------------------------------------------------------------
// Resolving of classes

Symbol* SystemDictionary::class_name_symbol(const char* name, Symbol* exception, TRAPS) {
  if (name == NULL) {
    THROW_MSG_0(exception, "No class name given");
  }
  if ((int)strlen(name) > Symbol::max_length()) {
    // It's impossible to create this class;  the name cannot fit
    // into the constant pool.
    Exceptions::fthrow(THREAD_AND_LOCATION, exception,
                       "Class name exceeds maximum length of %d: %s",
                       Symbol::max_length(),
                       name);
    return NULL;
  }
  // Callers should ensure that the name is never an illegal UTF8 string.
  assert(UTF8::is_legal_utf8((const unsigned char*)name, (int)strlen(name), false),
         "Class name is not a valid utf8 string.");

  // Make a new symbol for the class name.
  return SymbolTable::new_symbol(name);
}

#ifdef ASSERT
// Used to verify that class loading succeeded in adding k to the dictionary.
void verify_dictionary_entry(Symbol* class_name, InstanceKlass* k) {
  MutexLocker mu(SystemDictionary_lock);
  ClassLoaderData* loader_data = k->class_loader_data();
  Dictionary* dictionary = loader_data->dictionary();
  assert(class_name == k->name(), "Must be the same");
  InstanceKlass* kk = dictionary->find_class(JavaThread::current(), class_name);
  assert(kk == k, "should be present in dictionary");
}
#endif

static void handle_resolution_exception(Symbol* class_name, bool throw_error, TRAPS) {
  if (HAS_PENDING_EXCEPTION) {
    // If we have a pending exception we forward it to the caller, unless throw_error is true,
    // in which case we have to check whether the pending exception is a ClassNotFoundException,
    // and convert it to a NoClassDefFoundError and chain the original ClassNotFoundException.
    if (throw_error && PENDING_EXCEPTION->is_a(vmClasses::ClassNotFoundException_klass())) {
      ResourceMark rm(THREAD);
      Handle e(THREAD, PENDING_EXCEPTION);
      CLEAR_PENDING_EXCEPTION;
      THROW_MSG_CAUSE(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string(), e);
    } else {
      return// the caller will throw the incoming exception
    }
  }
  // If the class is not found, ie, caller has checked that klass is NULL, throw the appropriate
  // error or exception depending on the value of throw_error.
  ResourceMark rm(THREAD);
  if (throw_error) {
    THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), class_name->as_C_string());
  } else {
    THROW_MSG(vmSymbols::java_lang_ClassNotFoundException(), class_name->as_C_string());
  }
}

// Forwards to resolve_or_null

Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain,
                                         bool throw_error, TRAPS) {
  Klass* klass = resolve_or_null(class_name, class_loader, protection_domain, THREAD);
  // Check for pending exception or null klass, and throw exception
  if (HAS_PENDING_EXCEPTION || klass == NULL) {
    handle_resolution_exception(class_name, throw_error, CHECK_NULL);
  }
  return klass;
}

// Forwards to resolve_array_class_or_null or resolve_instance_class_or_null

Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) {
  if (Signature::is_array(class_name)) {
    return resolve_array_class_or_null(class_name, class_loader, protection_domain, THREAD);
  } else {
    assert(class_name != NULL && !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);
    }
  }
}

// Forwards to resolve_instance_class_or_null

Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
                                                     Handle class_loader,
                                                     Handle protection_domain,
                                                     TRAPS) {
  assert(Signature::is_array(class_name), "must be array");
  ResourceMark rm(THREAD);
  SignatureStream ss(class_name, false);
  int ndims = ss.skip_array_prefix();  // skip all '['s
  Klass* k = NULL;
  BasicType t = ss.type();
  if (ss.has_envelope()) {
    Symbol* obj_class = ss.as_symbol();
    k = SystemDictionary::resolve_instance_class_or_null(obj_class,
                                                         class_loader,
                                                         protection_domain,
                                                         CHECK_NULL);
    if (k != NULL) {
      k = k->array_klass(ndims, CHECK_NULL);
    }
  } else {
    k = Universe::typeArrayKlassObj(t);
    k = TypeArrayKlass::cast(k)->array_klass(ndims, CHECK_NULL);
  }
  return k;
}

static inline void log_circularity_error(Symbol* name, PlaceholderEntry* probe) {
  LogTarget(Debug, class, load, placeholders) lt;
  if (lt.is_enabled()) {
    ResourceMark rm;
    LogStream ls(lt);
    ls.print("ClassCircularityError detected for placeholder entry %s", name->as_C_string());
    probe->print_on(&ls);
    ls.cr();
  }
}

// Must be called for any superclass or superinterface resolution
// during class definition to allow class circularity checking
// superinterface callers:
//    parse_interfaces - from defineClass
// superclass callers:
//   ClassFileParser - from defineClass
//   load_shared_class - while loading a class from shared archive
//   resolve_instance_class_or_null:
//     via: handle_parallel_super_load
//      when resolving a class that has an existing placeholder with
//      a saved superclass [i.e. a defineClass is currently in progress]
//      If another thread is trying to resolve the class, it must do
//      superclass checks on its own thread to catch class circularity and
//      to avoid deadlock.
//
// resolve_super_or_fail adds a LOAD_SUPER placeholder to the placeholder table before calling
// resolve_instance_class_or_null. ClassCircularityError is detected when a LOAD_SUPER or LOAD_INSTANCE
// placeholder for the same thread, class, classloader is found.
// This can be seen with logging option: -Xlog:class+load+placeholders=debug.
//
InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name,
                                                       Symbol* super_name,
                                                       Handle class_loader,
                                                       Handle protection_domain,
                                                       bool is_superclass,
                                                       TRAPS) {

  assert(super_name != NULL, "null superclass for resolving");
  assert(!Signature::is_array(super_name), "invalid superclass name");
#if INCLUDE_CDS
  if (DumpSharedSpaces) {
    // Special processing for handling UNREGISTERED shared classes.
    InstanceKlass* k = SystemDictionaryShared::lookup_super_for_unregistered_class(class_name,
                           super_name, is_superclass);
    if (k) {
      return k;
    }
  }
#endif // INCLUDE_CDS

  // If klass is already loaded, just return the superclass or superinterface.
  // Make sure there's a placeholder for the class_name before resolving.
  // This is used as a claim that this thread is currently loading superclass/classloader
  // and for ClassCircularity checks.

  ClassLoaderData* loader_data = class_loader_data(class_loader);
  Dictionary* dictionary = loader_data->dictionary();

  // can't throw error holding a lock
  bool throw_circularity_error = false;
  {
    MutexLocker mu(THREAD, SystemDictionary_lock);
    InstanceKlass* klassk = dictionary->find_class(THREAD, class_name);
    InstanceKlass* quicksuperk;
    // To support parallel loading: if class is done loading, just return the superclass
    // if the super_name matches class->super()->name() and if the class loaders match.
    // Otherwise, a LinkageError will be thrown later.
    if (klassk != NULL && is_superclass &&
        ((quicksuperk = klassk->java_super()) != NULL) &&
         ((quicksuperk->name() == super_name) &&
            (quicksuperk->class_loader() == class_loader()))) {
           return quicksuperk;
    } else {
      // Must check ClassCircularity before checking if superclass is already loaded.
      PlaceholderEntry* probe = PlaceholderTable::get_entry(class_name, loader_data);
      if (probe && probe->check_seen_thread(THREAD, PlaceholderTable::LOAD_SUPER)) {
          log_circularity_error(class_name, probe);
          throw_circularity_error = true;
      }
    }

    if (!throw_circularity_error) {
      // Be careful not to exit resolve_super without removing this placeholder.
      PlaceholderEntry* newprobe = PlaceholderTable::find_and_add(class_name,
                                                                  loader_data,
                                                                  PlaceholderTable::LOAD_SUPER,
                                                                  super_name, THREAD);
    }
  }

  if (throw_circularity_error) {
      ResourceMark rm(THREAD);
      THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), class_name->as_C_string());
  }

  // Resolve the superclass or superinterface, check results on return
  InstanceKlass* superk =
    SystemDictionary::resolve_instance_class_or_null(super_name,
                                                     class_loader,
                                                     protection_domain,
                                                     THREAD);

  // Clean up placeholder entry.
  {
    MutexLocker mu(THREAD, SystemDictionary_lock);
    PlaceholderTable::find_and_remove(class_name, loader_data, PlaceholderTable::LOAD_SUPER, THREAD);
    SystemDictionary_lock->notify_all();
  }

  // Check for pending exception or null superk, and throw exception
  if (HAS_PENDING_EXCEPTION || superk == NULL) {
    handle_resolution_exception(super_name, true, CHECK_NULL);
  }

  return superk;
}

// We only get here if this thread finds that another thread
// has already claimed the placeholder token for the current operation,
// but that other thread either never owned or gave up the
// object lock
// Waits on SystemDictionary_lock to indicate placeholder table updated
// On return, caller must recheck placeholder table state
//
// We only get here if
//  1) custom classLoader, i.e. not bootstrap classloader
//  2) custom classLoader has broken the class loader objectLock
//     so another thread got here in parallel
//
// lockObject must be held.
// Complicated dance due to lock ordering:
// Must first release the classloader object lock to
// allow initial definer to complete the class definition
// and to avoid deadlock
// Reclaim classloader lock object with same original recursion count
// Must release SystemDictionary_lock after notify, since
// class loader lock must be claimed before SystemDictionary_lock
// to prevent deadlocks
//
// The notify allows applications that did an untimed wait() on
// the classloader object lock to not hang.
static void double_lock_wait(JavaThread* thread, Handle lockObject) {
  assert_lock_strong(SystemDictionary_lock);

  assert(EnableWaitForParallelLoad,
         "Only called when enabling legacy parallel class loading logic "
         "for non-parallel capable class loaders");
  assert(lockObject() != NULL, "lockObject must be non-NULL");
  bool calledholdinglock
      = ObjectSynchronizer::current_thread_holds_lock(thread, lockObject);
  assert(calledholdinglock, "must hold lock for notify");
  assert(!is_parallelCapable(lockObject), "lockObject must not be parallelCapable");
  // These don't throw exceptions.
  ObjectSynchronizer::notifyall(lockObject, thread);
  intx recursions = ObjectSynchronizer::complete_exit(lockObject, thread);
  SystemDictionary_lock->wait();
  SystemDictionary_lock->unlock();
  ObjectSynchronizer::reenter(lockObject, recursions, thread);
  SystemDictionary_lock->lock();
}

// 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
// detection for parallelCapable class loaders that lock on a per-class lock.
static void handle_parallel_super_load(Symbol* name,
                                       Symbol* superclassname,
                                       Handle class_loader,
                                       Handle protection_domain, TRAPS) {

  // superk is not used; resolve_super_or_fail is called for circularity check only.
  Klass* superk = SystemDictionary::resolve_super_or_fail(name,
                                                          superclassname,
                                                          class_loader,
                                                          protection_domain,
                                                          true,
                                                          CHECK);
}

// Bootstrap and non-parallel capable class loaders use the LOAD_INSTANCE placeholder to
// wait for parallel class loading and to check for circularity error for Xcomp when loading
// signature classes.
// parallelCapable class loaders do NOT wait for parallel loads to complete
static bool needs_load_placeholder(Handle class_loader) {
  return class_loader.is_null() || !is_parallelCapable(class_loader);
}

// For bootstrap and non-parallelCapable class loaders, check and wait for
// another thread to complete loading this class.
InstanceKlass* SystemDictionary::handle_parallel_loading(JavaThread* current,
                                                         Symbol* name,
                                                         ClassLoaderData* loader_data,
                                                         Handle lockObject,
                                                         bool* throw_circularity_error) {
  PlaceholderEntry* oldprobe = PlaceholderTable::get_entry(name, loader_data);
  if (oldprobe != NULL) {
    // only need check_seen_thread once, not on each loop
    // 6341374 java/lang/Instrument with -Xcomp
    if (oldprobe->check_seen_thread(current, PlaceholderTable::LOAD_INSTANCE)) {
      log_circularity_error(name, oldprobe);
      *throw_circularity_error = true;
      return NULL;
    } else {
      // Wait until the first thread has finished loading this class. Also wait until all the
      // threads trying to load its superclass have removed their placeholders.
      while (oldprobe != NULL &&
             (oldprobe->instance_load_in_progress() || oldprobe->super_load_in_progress())) {

        // We only get here if the application has released the
        // classloader lock when another thread was in the middle of loading a
        // superclass/superinterface for this class, and now
        // this thread is also trying to load this class.
        // To minimize surprises, the first thread that started to
        // load a class should be the one to complete the loading
        // with the classfile it initially expected.
        // This logic has the current thread wait once it has done
        // all the superclass/superinterface loading it can, until
        // the original thread completes the class loading or fails
        // If it completes we will use the resulting InstanceKlass
        // which we will find below in the systemDictionary.

        if (lockObject.is_null()) {
          SystemDictionary_lock->wait();
        } else if (EnableWaitForParallelLoad) {
          double_lock_wait(current, lockObject);
        } else {
          return NULL;
        }

        // Check if classloading completed while we were waiting
        InstanceKlass* check = loader_data->dictionary()->find_class(current, name);
        if (check != NULL) {
          // Klass is already loaded, so just return it
          return check;
        }
        // check if other thread failed to load and cleaned up
        oldprobe = PlaceholderTable::get_entry(name, loader_data);
      }
    }
  }
  return NULL;
}

void SystemDictionary::post_class_load_event(EventClassLoad* event, const InstanceKlass* k, const ClassLoaderData* init_cld) {
  assert(event != NULL, "invariant");
  assert(k != NULL, "invariant");
  event->set_loadedClass(k);
  event->set_definingClassLoader(k->class_loader_data());
  event->set_initiatingClassLoader(init_cld);
  event->commit();
}

// SystemDictionary::resolve_instance_class_or_null is the main function for class name resolution.
// After checking if the InstanceKlass already exists, it checks for ClassCircularityError and
// whether the thread must wait for loading in parallel.  It eventually calls load_instance_class,
// which will load the class via the bootstrap loader or call ClassLoader.loadClass().
// This can return NULL, an exception or an InstanceKlass.
InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
                                                                Handle class_loader,
                                                                Handle protection_domain,
                                                                TRAPS) {
  // name must be in the form of "java/lang/Object" -- cannot be "Ljava/lang/Object;"
  assert(name != NULL && !Signature::is_array(name) &&
         !Signature::has_envelope(name), "invalid class name");

  EventClassLoad class_load_start_event;

  HandleMark hm(THREAD);

  // Fix for 4474172; see evaluation for more details
  class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
  ClassLoaderData* loader_data = register_loader(class_loader);
  Dictionary* dictionary = loader_data->dictionary();

  // Do lookup to see if class already exists and the protection domain
  // has the right access.
  // This call uses find which checks protection domain already matches
  // All subsequent calls use find_class, and set loaded_class so that
  // before we return a result, we call out to java to check for valid protection domain.
  InstanceKlass* probe = dictionary->find(THREAD, name, protection_domain);
  if (probe != NULL) return probe;

  // Non-bootstrap class loaders will call out to class loader and
  // define via jvm/jni_DefineClass which will acquire the
  // class loader object lock to protect against multiple threads
  // defining the class in parallel by accident.
  // This lock must be acquired here so the waiter will find
  // any successful result in the SystemDictionary and not attempt
  // the define.
  // ParallelCapable class loaders and the bootstrap classloader
  // do not acquire lock here.
  Handle lockObject = get_loader_lock_or_null(class_loader);
  ObjectLocker ol(lockObject, THREAD);

  bool super_load_in_progress  = false;
  InstanceKlass* loaded_class = NULL;
  Symbol* superclassname = NULL;

  assert(THREAD->can_call_java(),
         "can not load classes with compiler thread: class=%s, classloader=%s",
         name->as_C_string(),
         class_loader.is_null() ? "null" : class_loader->klass()->name()->as_C_string());

  // Check again (after locking) if the class already exists in SystemDictionary
  {
    MutexLocker mu(THREAD, SystemDictionary_lock);
    InstanceKlass* check = dictionary->find_class(THREAD, name);
    if (check != NULL) {
      // InstanceKlass is already loaded, but we still need to check protection domain below.
      loaded_class = check;
    } else {
      PlaceholderEntry* placeholder = PlaceholderTable::get_entry(name, loader_data);
      if (placeholder != NULL && placeholder->super_load_in_progress()) {
         super_load_in_progress = true;
         superclassname = placeholder->supername();
         assert(superclassname != NULL, "superclass has to have a name");
      }
    }
  }

  // If the class is in the placeholder table with super_class set,
  // handle superclass loading in progress.
  if (super_load_in_progress) {
    handle_parallel_super_load(name, superclassname,
                               class_loader,
                               protection_domain,
                               CHECK_NULL);
  }

  bool throw_circularity_error = false;
  if (loaded_class == NULL) {
    bool load_placeholder_added = false;

    // Add placeholder entry to record loading instance class
    // Four cases:
    // case 1. Bootstrap classloader
    //    This classloader supports parallelism at the classloader level
    //    but only allows a single thread to load a class/classloader pair.
    //    The LOAD_INSTANCE placeholder is the mechanism for mutual exclusion.
    // case 2. parallelCapable user level classloaders
    //    These class loaders lock a per-class object lock when ClassLoader.loadClass()
    //    is called. A LOAD_INSTANCE placeholder isn't used for mutual exclusion.
    // case 3. traditional classloaders that rely on the classloader object lock
    //    There should be no need for need for LOAD_INSTANCE, except:
    // case 4. traditional class loaders that break the classloader object lock
    //    as a legacy deadlock workaround. Detection of this case requires that
    //    this check is done while holding the classloader object lock,
    //    and that lock is still held when calling classloader's loadClass.
    //    For these classloaders, we ensure that the first requestor
    //    completes the load and other requestors wait for completion.
    {
      MutexLocker mu(THREAD, SystemDictionary_lock);
      if (needs_load_placeholder(class_loader)) {
        loaded_class = handle_parallel_loading(THREAD,
                                               name,
                                               loader_data,
                                               lockObject,
                                               &throw_circularity_error);
      }

      // Recheck if the class has been loaded for all class loader cases and
      // add a LOAD_INSTANCE placeholder while holding the SystemDictionary_lock.
      if (!throw_circularity_error && loaded_class == NULL) {
        InstanceKlass* check = dictionary->find_class(THREAD, name);
        if (check != NULL) {
          loaded_class = check;
        } else if (needs_load_placeholder(class_loader)) {
          // Add the LOAD_INSTANCE token. Threads will wait on loading to complete for this thread,
          // and check for ClassCircularityError with -Xcomp.
          PlaceholderEntry* newprobe = PlaceholderTable::find_and_add(name, loader_data,
                                                                      PlaceholderTable::LOAD_INSTANCE,
                                                                      NULL,
                                                                      THREAD);
          load_placeholder_added = true;
        }
      }
    }

    // Must throw error outside of owning lock
    if (throw_circularity_error) {
      assert(!HAS_PENDING_EXCEPTION && !load_placeholder_added, "circularity error cleanup");
      ResourceMark rm(THREAD);
      THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), name->as_C_string());
    }

    // Be careful when modifying this code: once you have run
    // PlaceholderTable::find_and_add(PlaceholderTable::LOAD_INSTANCE),
    // you need to find_and_remove it before returning.
    // So be careful to not exit with a CHECK_ macro between these calls.

    if (loaded_class == NULL) {
      // Do actual loading
      loaded_class = load_instance_class(name, class_loader, THREAD);
    }

    if (load_placeholder_added) {
      // clean up placeholder entries for LOAD_INSTANCE success or error
      // This brackets the SystemDictionary updates for both defining
      // and initiating loaders
      MutexLocker mu(THREAD, SystemDictionary_lock);
      PlaceholderTable::find_and_remove(name, loader_data, PlaceholderTable::LOAD_INSTANCE, THREAD);
      SystemDictionary_lock->notify_all();
    }
  }

  if (HAS_PENDING_EXCEPTION || loaded_class == NULL) {
    return NULL;
  }

  if (class_load_start_event.should_commit()) {
    post_class_load_event(&class_load_start_event, loaded_class, loader_data);
  }

  // Make sure we have the right class in the dictionary
  DEBUG_ONLY(verify_dictionary_entry(name, loaded_class));

  // Check if the protection domain is present it has the right access
  if (protection_domain() != NULL) {
    // Verify protection domain. If it fails an exception is thrown
    dictionary->validate_protection_domain(loaded_class, class_loader, protection_domain, CHECK_NULL);
  }

  return loaded_class;
}


// This routine does not lock the system dictionary.
//
// Since readers don't hold a lock, we must make sure that system
// dictionary entries are added to in a safe way (all links must
// be updated in an MT-safe manner). All entries are removed during class
// unloading, when this class loader is no longer referenced.
//
// Callers should be aware that an entry could be added just after
// Dictionary is read here, so the caller will not see
// the new entry.

InstanceKlass* SystemDictionary::find_instance_klass(Thread* current,
                                                     Symbol* class_name,
                                                     Handle class_loader,
                                                     Handle protection_domain) {

  // The result of this call should be consistent with the result
  // of the call to resolve_instance_class_or_null().
  // See evaluation 6790209 and 4474172 for more details.
  oop class_loader_oop = java_lang_ClassLoader::non_reflection_class_loader(class_loader());
  ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(class_loader_oop);

  if (loader_data == NULL) {
    // If the ClassLoaderData has not been setup,
    // then the class loader has no entries in the dictionary.
    return NULL;
  }

  Dictionary* dictionary = loader_data->dictionary();
  return dictionary->find(current, class_name, protection_domain);
}

// Look for a loaded instance or array klass by name.  Do not do any loading.
// return NULL in case of error.
Klass* SystemDictionary::find_instance_or_array_klass(Thread* current,
                                                      Symbol* class_name,
                                                      Handle class_loader,
                                                      Handle protection_domain) {
  Klass* k = NULL;
  assert(class_name != NULL, "class name must be non NULL");

  if (Signature::is_array(class_name)) {
    // The name refers to an array.  Parse the name.
    // 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 != NULL) {
      k = k->array_klass_or_null(ndims);
    }
  } else {
    k = find_instance_klass(current, class_name, class_loader, protection_domain);
  }
  return k;
}

// Note: this method is much like resolve_class_from_stream, but
// does not publish the classes in the SystemDictionary.
// Handles Lookup.defineClass hidden.
InstanceKlass* SystemDictionary::resolve_hidden_class_from_stream(
                                                     ClassFileStream* st,
                                                     Symbol* class_name,
                                                     Handle class_loader,
                                                     const ClassLoadInfo& cl_info,
                                                     TRAPS) {

  EventClassLoad class_load_start_event;
  ClassLoaderData* loader_data;

  // - for hidden classes that are not strong: create a new CLD that has a class holder and
  //                                           whose loader is the Lookup class's loader.
  // - for hidden class: add the class to the Lookup class's loader's CLD.
  assert (cl_info.is_hidden(), "only used for hidden classes");
  bool create_mirror_cld = !cl_info.is_strong_hidden();
  loader_data = register_loader(class_loader, create_mirror_cld);

  assert(st != NULL, "invariant");
  assert(st->need_verify(), "invariant");

  // Parse stream and create a klass.
  InstanceKlass* k = KlassFactory::create_from_stream(st,
                                                      class_name,
                                                      loader_data,
                                                      cl_info,
                                                      CHECK_NULL);
  assert(k != NULL, "no klass created");

  // Hidden classes that are not strong must update ClassLoaderData holder
  // so that they can be unloaded when the mirror is no longer referenced.
  if (!cl_info.is_strong_hidden()) {
    k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror()));
  }

  {
    MutexLocker mu_r(THREAD, Compile_lock);
    // Add to class hierarchy, and do possible deoptimizations.
    add_to_hierarchy(k);
    // But, do not add to dictionary.
  }

  k->link_class(CHECK_NULL);

  // notify jvmti
  if (JvmtiExport::should_post_class_load()) {
    JvmtiExport::post_class_load(THREAD, k);
  }
  if (class_load_start_event.should_commit()) {
    post_class_load_event(&class_load_start_event, k, loader_data);
  }

  return k;
}

// Add a klass to the system from a stream (called by jni_DefineClass and
// JVM_DefineClass).
// Note: class_name can be NULL. In that case we do not know the name of
// the class until we have parsed the stream.
// This function either returns an InstanceKlass or throws an exception.  It does
// not return NULL without a pending exception.
InstanceKlass* SystemDictionary::resolve_class_from_stream(
                                                     ClassFileStream* st,
                                                     Symbol* class_name,
                                                     Handle class_loader,
                                                     const ClassLoadInfo& cl_info,
                                                     TRAPS) {

  HandleMark hm(THREAD);

  ClassLoaderData* loader_data = register_loader(class_loader);

  // Classloaders that support parallelism, e.g. bootstrap classloader,
  // do not acquire lock here
  Handle lockObject = get_loader_lock_or_null(class_loader);
  ObjectLocker ol(lockObject, THREAD);

  // Parse the stream and create a klass.
  // Note that we do this even though this klass might
  // already be present in the SystemDictionary, otherwise we would not
  // throw potential ClassFormatErrors.
 InstanceKlass* k = NULL;

#if INCLUDE_CDS
  if (!DumpSharedSpaces) {
    k = SystemDictionaryShared::lookup_from_stream(class_name,
                                                   class_loader,
                                                   cl_info.protection_domain(),
                                                   st,
                                                   CHECK_NULL);
  }
#endif

  if (k == NULL) {
    k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, CHECK_NULL);
  }

  assert(k != NULL, "no klass created");
  Symbol* h_name = k->name();
  assert(class_name == NULL || class_name == h_name, "name mismatch");

  // Add class just loaded
  // If a class loader supports parallel classloading, handle parallel define requests.
  // find_or_define_instance_class may return a different InstanceKlass,
  // in which case the old k would be deallocated
  if (is_parallelCapable(class_loader)) {
    k = find_or_define_instance_class(h_name, class_loader, k, CHECK_NULL);
  } else {
    define_instance_class(k, class_loader, THREAD);

    // If defining the class throws an exception register 'k' for cleanup.
    if (HAS_PENDING_EXCEPTION) {
      assert(k != NULL, "Must have an instance klass here!");
      loader_data->add_to_deallocate_list(k);
      return NULL;
    }
  }

  // Make sure we have an entry in the SystemDictionary on success
  DEBUG_ONLY(verify_dictionary_entry(h_name, k));

  return k;
}

InstanceKlass* SystemDictionary::resolve_from_stream(ClassFileStream* st,
                                                     Symbol* class_name,
                                                     Handle class_loader,
                                                     const ClassLoadInfo& cl_info,
                                                     TRAPS) {
  if (cl_info.is_hidden()) {
    return resolve_hidden_class_from_stream(st, class_name, class_loader, cl_info, CHECK_NULL);
  } else {
    return resolve_class_from_stream(st, class_name, class_loader, cl_info, CHECK_NULL);
  }
}


#if INCLUDE_CDS
// 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() != NULL) {
      return false;
    }
  } else if (ik->is_shared_platform_class()) {
    if (class_loader() != java_platform_loader()) {
      return false;
    }
  } else if (ik->is_shared_app_class()) {
    if (class_loader() != java_system_loader()) {
      return false;
    }
  } else {
    // ik was loaded by a custom loader during dump time
    if (class_loader_data(class_loader)->is_builtin_class_loader_data()) {
      return false;
    } else {
      return true;
    }
  }

  // (2) Check if we are loading into the same module from the same location as in dump time.

  if (MetaspaceShared::use_optimized_module_handling()) {
    // Class visibility has not changed between dump time and run time, so a class
    // that was visible (and thus archived) during dump time is always visible during runtime.
    assert(SystemDictionary::is_shared_class_visible_impl(class_name, ik, pkg_entry, class_loader),
           "visibility cannot change between dump time and runtime");
    return true;
  }
  return is_shared_class_visible_impl(class_name, ik, pkg_entry, class_loader);
}

bool SystemDictionary::is_shared_class_visible_impl(Symbol* class_name,
                                                    InstanceKlass* ik,
                                                    PackageEntry* pkg_entry,
                                                    Handle class_loader) {
  int scp_index = ik->shared_classpath_index();
  assert(!ik->is_shared_unregistered_class(), "this function should be called for built-in classes only");
  assert(scp_index >= 0, "must be");
  SharedClassPathEntry* scp_entry = FileMapInfo::shared_path(scp_index);
  if (!Universe::is_module_initialized()) {
    assert(scp_entry != NULL, "must be");
    // At this point, no modules have been defined yet. KlassSubGraphInfo::check_allowed_klass()
    // has restricted the classes can be loaded at this step to be only:
    // [1] scp_entry->is_modules_image(): classes in java.base, or,
    // [2] HeapShared::is_a_test_class_in_unnamed_module(ik): classes in bootstrap/unnamed module
    assert(scp_entry->is_modules_image() || HeapShared::is_a_test_class_in_unnamed_module(ik),
           "only these classes can be loaded before the module system is initialized");
    assert(class_loader.is_null(), "sanity");
    return true;
  }

  if (pkg_entry == NULL) {
    // We might have looked up pkg_entry before the module system was initialized.
    // Need to reload it now.
    TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);
    if (pkg_name != NULL) {
      pkg_entry = ClassLoaderData::class_loader_data(class_loader())->packages()->lookup_only(pkg_name);
    }
  }

  ModuleEntry* mod_entry = (pkg_entry == NULL) ? NULL : pkg_entry->module();
  bool should_be_in_named_module = (mod_entry != NULL && mod_entry->is_named());
  bool was_archived_from_named_module = scp_entry->in_named_module();
  bool visible;

  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;
    }
  } else {
    if (should_be_in_named_module) {
      // During dump time, this class was in an unnamed, but at run time, this class should be
      // in a named module.
      visible = false;
    } else {
      visible = true;
    }
  }

  return visible;
}

bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, InstanceKlass* super_type,
                                                     Handle class_loader,  Handle protection_domain,
                                                     bool is_superclass, TRAPS) {
  assert(super_type->is_shared(), "must be");

  // Quick check if the super type has been already loaded.
  // + Don't do it for unregistered classes -- they can be unloaded so
  //   super_type->class_loader_data() could be stale.
  // + Don't check if loader data is NULL, ie. the super_type isn't fully loaded.
  if (!super_type->is_shared_unregistered_class() && super_type->class_loader_data() != NULL) {
    // Check if the superclass is loaded by the current class_loader
    Symbol* name = super_type->name();
    InstanceKlass* check = find_instance_klass(THREAD, name, class_loader, protection_domain);
    if (check == super_type) {
      return true;
    }
  }

  Klass *found = resolve_super_or_fail(klass->name(), super_type->name(),
                                       class_loader, protection_domain, is_superclass, CHECK_0);
  if (found == super_type) {
    return true;
  } else {
    // The dynamically resolved super type is not the same as the one we used during dump time,
    // so we cannot use the class.
    return false;
  }
}

bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle class_loader,
                                                      Handle protection_domain, TRAPS) {
  // Check the superclass and interfaces. They must be the same
  // as in dump time, because the layout of <ik> depends on
  // the specific layout of ik->super() and ik->local_interfaces().
  //
  // If unexpected superclass or interfaces are found, we cannot
  // load <ik> from the shared archive.

  if (ik->super() != NULL &&
      !check_shared_class_super_type(ik, InstanceKlass::cast(ik->super()),
                                     class_loader, protection_domain, true, THREAD)) {
    return false;
  }

  Array<InstanceKlass*>* interfaces = ik->local_interfaces();
  int num_interfaces = interfaces->length();
  for (int index = 0; index < num_interfaces; index++) {
    if (!check_shared_class_super_type(ik, interfaces->at(index), class_loader, protection_domain, false, THREAD)) {
      return false;
    }
  }

  return true;
}

InstanceKlass* SystemDictionary::load_shared_lambda_proxy_class(InstanceKlass* ik,
                                                                Handle class_loader,
                                                                Handle protection_domain,
                                                                PackageEntry* pkg_entry,
                                                                TRAPS) {
  InstanceKlass* shared_nest_host = SystemDictionaryShared::get_shared_nest_host(ik);
  assert(shared_nest_host->is_shared(), "nest host must be in CDS archive");
  Symbol* cn = shared_nest_host->name();
  Klass *s = resolve_or_fail(cn, class_loader, protection_domain, true, CHECK_NULL);
  if (s != shared_nest_host) {
    // The dynamically resolved nest_host is not the same as the one we used during dump time,
    // so we cannot use ik.
    return NULL;
  } else {
    assert(s->is_shared(), "must be");
  }

  InstanceKlass* loaded_ik = load_shared_class(ik, class_loader, protection_domain, NULL, pkg_entry, CHECK_NULL);

  if (loaded_ik != NULL) {
    assert(shared_nest_host->is_same_class_package(ik),
           "lambda proxy class and its nest host must be in the same package");
  }

  // The lambda proxy class and its nest host have the same class loader and class loader data,
  // as verified in SystemDictionaryShared::add_lambda_proxy_class()
  assert(shared_nest_host->class_loader() == class_loader(), "mismatched class loader");
  assert(shared_nest_host->class_loader_data() == ClassLoaderData::class_loader_data(class_loader()), "mismatched class loader data");
  ik->set_nest_host(shared_nest_host);

  return loaded_ik;
}

InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
                                                   Handle class_loader,
                                                   Handle protection_domain,
                                                   const ClassFileStream *cfs,
                                                   PackageEntry* pkg_entry,
                                                   TRAPS) {
  assert(ik != NULL, "sanity");
  assert(!ik->is_unshareable_info_restored(), "shared class can be loaded only once");
  Symbol* class_name = ik->name();

  if (!is_shared_class_visible(class_name, ik, pkg_entry, class_loader)) {
    return NULL;
  }

  if (!check_shared_class_super_types(ik, class_loader, protection_domain, THREAD)) {
    return NULL;
  }

  InstanceKlass* new_ik = NULL;
  // 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(
      ik, class_name, class_loader, protection_domain, cfs, CHECK_NULL);
  }
  if (new_ik != NULL) {
    // The class is changed by CFLH. Return the new class. The shared class is
    // not used.
    return new_ik;
  }

  // Adjust methods to recover missing data.  They need addresses for
  // interpreter entry points and their default native method address
  // must be reset.

  // Shared classes are all currently loaded by either the bootstrap or
  // internal parallel class loaders, so this will never cause a deadlock
  // on a custom class loader lock.
  // Since this class is already locked with parallel capable class
  // loaders, including the bootstrap loader via the placeholder table,
  // this lock is currently a nop.

  ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
  {
    HandleMark hm(THREAD);
    Handle lockObject = get_loader_lock_or_null(class_loader);
    ObjectLocker ol(lockObject, THREAD);
    // prohibited package check assumes all classes loaded from archive call
    // 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, NULL, NULL);

  // For boot loader, ensure that GetSystemPackage knows that a class in this
  // package was loaded.
  if (loader_data->is_the_null_class_loader_data()) {
    int path_index = ik->shared_classpath_index();
    ik->set_classpath_index(path_index);
  }

  // notify a class loaded from shared object
  ClassLoadingService::notify_class_loaded(ik, true /* shared class */);
}

#endif // INCLUDE_CDS

InstanceKlass* SystemDictionary::load_instance_class_impl(Symbol* class_name, Handle class_loader, TRAPS) {

  if (class_loader.is_null()) {
    ResourceMark rm(THREAD);
    PackageEntry* pkg_entry = NULL;
    bool search_only_bootloader_append = false;
    ClassLoaderData *loader_data = class_loader_data(class_loader);

    // Find the package in the boot loader's package entry table.
    TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name);
    if (pkg_name != NULL) {
      pkg_entry = loader_data->packages()->lookup_only(pkg_name);
    }

    // Prior to attempting to load the class, enforce the boot loader's
    // visibility boundaries.
    if (!Universe::is_module_initialized()) {
      // During bootstrapping, prior to module initialization, any
      // class attempting to be loaded must be checked against the
      // java.base packages in the boot loader's PackageEntryTable.
      // No class outside of java.base is allowed to be loaded during
      // this bootstrapping window.
      if (pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
        // Class is either in the unnamed package or in
        // a named package within the unnamed module.  Either
        // case is outside of java.base, do not attempt to
        // load the class post java.base definition.  If
        // java.base has not been defined, let the class load
        // and its package will be checked later by
        // ModuleEntryTable::verify_javabase_packages.
        if (ModuleEntryTable::javabase_defined()) {
          return NULL;
        }
      } else {
        // Check that the class' package is defined within java.base.
        ModuleEntry* mod_entry = pkg_entry->module();
        Symbol* mod_entry_name = mod_entry->name();
        if (mod_entry_name->fast_compare(vmSymbols::java_base()) != 0) {
          return NULL;
        }
      }
    } else {
      // After the module system has been initialized, check if the class'
      // package is in a module defined to the boot loader.
      if (pkg_name == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
        // Class is either in the unnamed package, in a named package
        // within a module not defined to the boot loader or in a
        // a named package within the unnamed module.  In all cases,
        // limit visibility to search for the class only in the boot
        // loader's append path.
        if (!ClassLoader::has_bootclasspath_append()) {
           // If there is no bootclasspath append entry, no need to continue
           // searching.
           return NULL;
        }
        search_only_bootloader_append = true;
      }
    }

    // Prior to bootstrapping's module initialization, never load a class outside
    // of the boot loader's module path
    assert(Universe::is_module_initialized() ||
           !search_only_bootloader_append,
           "Attempt to load a class outside of boot loader's module path");

    // Search for classes in the CDS archive.
    InstanceKlass* k = NULL;

#if INCLUDE_CDS
    if (UseSharedSpaces)
    {
      PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time());
      InstanceKlass* ik = SystemDictionaryShared::find_builtin_class(class_name);
      if (ik != NULL && ik->is_shared_boot_class() && !ik->shared_loading_failed()) {
        SharedClassLoadingMark slm(THREAD, ik);
        k = load_shared_class(ik, class_loader, Handle(), NULL,  pkg_entry, CHECK_NULL);
      }
    }
#endif

    if (k == NULL) {
      // Use VM class loader
      PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
      k = ClassLoader::load_class(class_name, search_only_bootloader_append, CHECK_NULL);
    }

    // find_or_define_instance_class may return a different InstanceKlass
    if (k != NULL) {
      CDS_ONLY(SharedClassLoadingMark slm(THREAD, k);)
      k = find_or_define_instance_class(class_name, class_loader, k, CHECK_NULL);
    }
    return k;
  } else {
    // Use user specified class loader to load class. Call loadClass operation on class_loader.
    ResourceMark rm(THREAD);

    JavaThread* jt = THREAD;

    PerfClassTraceTime vmtimer(ClassLoader::perf_app_classload_time(),
                               ClassLoader::perf_app_classload_selftime(),
                               ClassLoader::perf_app_classload_count(),
                               jt->get_thread_stat()->perf_recursion_counts_addr(),
                               jt->get_thread_stat()->perf_timers_addr(),
                               PerfClassTraceTime::CLASS_LOAD);

    // Translate to external class name format, i.e., convert '/' chars to '.'
    Handle string = java_lang_String::externalize_classname(class_name, CHECK_NULL);

    JavaValue result(T_OBJECT);

    InstanceKlass* spec_klass = vmClasses::ClassLoader_klass();

    // Call public unsynchronized loadClass(String) directly for all class loaders.
    // For parallelCapable class loaders, JDK >=7, loadClass(String, boolean) will
    // acquire a class-name based lock rather than the class loader object lock.
    // JDK < 7 already acquire the class loader lock in loadClass(String, boolean).
    JavaCalls::call_virtual(&result,
                            class_loader,
                            spec_klass,
                            vmSymbols::loadClass_name(),
                            vmSymbols::string_class_signature(),
                            string,
                            CHECK_NULL);

    assert(result.get_type() == T_OBJECT, "just checking");
    oop obj = result.get_oop();

    // Primitive classes return null since forName() can not be
    // used to obtain any of the Class objects representing primitives or void
    if ((obj != NULL) && !(java_lang_Class::is_primitive(obj))) {
      InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(obj));
      // For user defined Java class loaders, check that the name returned is
      // the same as that requested.  This check is done for the bootstrap
      // loader when parsing the class file.
      if (class_name == k->name()) {
        return k;
      }
    }
    // Class is not found or has the wrong name, return NULL
    return NULL;
  }
}

InstanceKlass* SystemDictionary::load_instance_class(Symbol* name,
                                                     Handle class_loader,
                                                     TRAPS) {

  InstanceKlass* loaded_class = load_instance_class_impl(name, class_loader, CHECK_NULL);

  // If everything was OK (no exceptions, no null return value), and
  // class_loader is NOT the defining loader, do a little more bookkeeping.
  if (loaded_class != NULL &&
    loaded_class->class_loader() != class_loader()) {

    check_constraints(loaded_class, class_loader, false, CHECK_NULL);

    // Record dependency for non-parent delegation.
    // This recording keeps the defining class loader of the klass (loaded_class) found
    // from being unloaded while the initiating class loader is loaded
    // even if the reference to the defining class loader is dropped
    // before references to the initiating class loader.
    ClassLoaderData* loader_data = class_loader_data(class_loader);
    loader_data->record_dependency(loaded_class);

    { // Grabbing the Compile_lock prevents systemDictionary updates
      // during compilations.
      MutexLocker mu(THREAD, Compile_lock);
      update_dictionary(THREAD, loaded_class, class_loader);
    }

    if (JvmtiExport::should_post_class_load()) {
      JvmtiExport::post_class_load(THREAD, loaded_class);
    }
  }
  return loaded_class;
}

static void post_class_define_event(InstanceKlass* k, const ClassLoaderData* def_cld) {
  EventClassDefine event;
  if (event.should_commit()) {
    event.set_definedClass(k);
    event.set_definingClassLoader(def_cld);
    event.commit();
  }
}

void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_loader, TRAPS) {

  ClassLoaderData* loader_data = k->class_loader_data();
  assert(loader_data->class_loader() == class_loader(), "they must be the same");

  // Bootstrap and other parallel classloaders don't acquire a lock,
  // they use placeholder token.
  // If a parallelCapable class loader calls define_instance_class instead of
  // find_or_define_instance_class to get here, we have a timing
  // hole with systemDictionary updates and check_constraints
  if (!is_parallelCapable(class_loader)) {
    assert(ObjectSynchronizer::current_thread_holds_lock(THREAD,
           get_loader_lock_or_null(class_loader)),
           "define called without lock");
  }

  // Check class-loading constraints. Throw exception if violation is detected.
  // Grabs and releases SystemDictionary_lock
  // The check_constraints/find_class call and update_dictionary sequence
  // must be "atomic" for a specific class/classloader pair so we never
  // define two different instanceKlasses for that class/classloader pair.
  // Existing classloaders will call define_instance_class with the
  // classloader lock held
  // Parallel classloaders will call find_or_define_instance_class
  // which will require a token to perform the define class
  Symbol*  name_h = k->name();
  Dictionary* dictionary = loader_data->dictionary();
  check_constraints(k, class_loader, true, CHECK);

  // Register class just loaded with class loader (placed in ArrayList)
  // Note we do this before updating the dictionary, as this can
  // fail with an OutOfMemoryError (if it does, we will *not* put this
  // class in the dictionary and will not update the class hierarchy).
  // JVMTI FollowReferences needs to find the classes this way.
  if (k->class_loader() != NULL) {
    methodHandle m(THREAD, Universe::loader_addClass_method());
    JavaValue result(T_VOID);
    JavaCallArguments args(class_loader);
    args.push_oop(Handle(THREAD, k->java_mirror()));
    JavaCalls::call(&result, m, &args, CHECK);
  }

  // Add the new class. We need recompile lock during update of CHA.
  {
    MutexLocker mu_r(THREAD, Compile_lock);

    // Add to class hierarchy, and do possible deoptimizations.
    add_to_hierarchy(k);

    // Add to systemDictionary - so other classes can see it.
    // Grabs and releases SystemDictionary_lock
    update_dictionary(THREAD, k, class_loader);
  }

  // notify jvmti
  if (JvmtiExport::should_post_class_load()) {
    JvmtiExport::post_class_load(THREAD, k);
  }
  post_class_define_event(k, loader_data);
}

// Support parallel classloading
// All parallel class loaders, including bootstrap classloader
// lock a placeholder entry for this class/class_loader pair
// to allow parallel defines of different classes for this class loader
// With AllowParallelDefine flag==true, in case they do not synchronize around
// FindLoadedClass/DefineClass, calls, we check for parallel
// loading for them, wait if a defineClass is in progress
// and return the initial requestor's results
// This flag does not apply to the bootstrap classloader.
// With AllowParallelDefine flag==false, call through to define_instance_class
// which will throw LinkageError: duplicate class definition.
// False is the requested default.
// For better performance, the class loaders should synchronize
// findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they
// potentially waste time reading and parsing the bytestream.
// Note: VM callers should ensure consistency of k/class_name,class_loader
// Be careful when modifying this code: once you have run
// PlaceholderTable::find_and_add(PlaceholderTable::DEFINE_CLASS),
--> --------------------

--> maximum size reached

--> --------------------

99%


¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.63Bemerkung:  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge