/* * Find a class from a given class loader. Throws ClassNotFoundException. * name: name of class * init: whether initialization is done * loader: class loader to look up the class. This may not be the same as the caller's * class loader. * caller: initiating class. The initiating class may be null when a security * manager is not installed. */ JNIEXPORT jclass JNICALL JVM_FindClassFromCaller(JNIEnv *env, constchar *name, jboolean init, jobject loader, jclass caller);
JVM_ENTRY(jclass, JVM_FindClassFromCaller(JNIEnv* env, constchar* name, jboolean init, jobject loader, jclass caller)) JVMWrapper2("JVM_FindClassFromCaller %s throws ClassNotFoundException", name); //Java libraries should ensure that name is never null... if (name == NULL || (int)strlen(name) > Symbol::max_length()) { //It's impossible to create this class; the name cannot fit //into the constant pool. THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name); }
oop loader_oop = JNIHandles::resolve(loader); oop from_class = JNIHandles::resolve(caller); oop protection_domain = NULL; //If loader is null, shouldn't call ClassLoader.checkPackageAccess; otherwise get //NPE. Put it in another way, the bootstrap class loader has all permission and //thus no checkPackageAccess equivalence in the VM class loader. //The caller is also passed as NULL by the java code if there is no security //manager to avoid the performance cost of getting the calling class. if (from_class != NULL && loader_oop != NULL) { protection_domain = java_lang_Class::as_Klass(from_class)->protection_domain(); }
if (TraceClassResolution && result != NULL) { trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); } return result; JVM_END
jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) { //Security Note: //The Java level wrapper will perform the necessary security check allowing //us to pass the NULL as the initiating class loader. The VM is responsible for //the checkPackageAccess relative to the initiating class loader via the //protection_domain. The protection_domain is passed as NULL by the java code //if there is no security manager in 3-arg Class.forName(). Klass* klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL);
KlassHandle klass_handle(THREAD, klass); //Check if we should initialize the class if (init && klass_handle->oop_is_instance()) { klass_handle->initialize(CHECK_NULL); } return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror()); }
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { //First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { longt0= System.nanoTime(); //双亲委派逻辑的体现之处 try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { //ClassNotFoundException thrown if class not found //from the non-null parent class loader }
if (c == null) { //If still not found, then invoke findClass in order //to find the class. longt1= System.nanoTime(); c = findClass(name);
//this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
constint str_len = (int)strlen(str); if (str_len > Symbol::max_length()) { //It's impossible to create this class; the name cannot fit //into the constant pool. returnNULL; } TempNewSymbol klass_name = SymbolTable::new_symbol(str, str_len, CHECK_NULL);
//Security Note: //The Java level wrapper will perform the necessary security check allowing //us to pass the NULL as the initiating class loader. Handle h_loader(THREAD, JNIHandles::resolve(loader)); if (UsePerfData) { is_lock_held_by_thread(h_loader, ClassLoader::sync_JVMFindLoadedClassLockFreeCounter(), THREAD); }
//核心调用 Klass* k = SystemDictionary::find_instance_or_array_klass(klass_name, h_loader, Handle(), CHECK_NULL); #if INCLUDE_CDS if (k == NULL) { //If the class is not already loaded, try to see if it's in the shared //archive for the current classloader (h_loader). instanceKlassHandle ik = SystemDictionaryShared::find_or_load_shared_class( klass_name, h_loader, CHECK_NULL); k = ik(); } #endif return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror()); JVM_END
//The existence or signature of this method is not guaranteed since it //supports a private method. This method will be changed in 1.7. JNIEXPORT jclass JNICALL Java_java_lang_ClassLoader_defineClass0(JNIEnv *env, jobject loader, jstring name, jbyteArray data, jint offset, jint length, jobject pd) { //转调用Java_java_lang_ClassLoader_defineClass1 return Java_java_lang_ClassLoader_defineClass1(env, loader, name, data, offset, length, pd, NULL); }
if (data == NULL) { JNU_ThrowNullPointerException(env, 0); return0; }
/* Work around 4153825. malloc crashes on Solaris when passed a * negative size. */ if (length < 0) { JNU_ThrowArrayIndexOutOfBoundsException(env, 0); return0; }
body = (jbyte *)malloc(length);
if (body == 0) { JNU_ThrowOutOfMemoryError(env, 0); return0; }
assert(data != NULL); //caller fails if data is null. assert(length >= 0); //caller passes ByteBuffer.remaining() for length, so never neg. //caller passes ByteBuffer.position() for offset, and capacity() >= position() + remaining() assert((*env)->GetDirectBufferCapacity(env, data) >= (offset + length));
body = (*env)->GetDirectBufferAddress(env, data);
if (body == 0) { JNU_ThrowNullPointerException(env, 0); return0; }
if (UsePerfData) { ClassLoader::perf_app_classfile_bytes_read()->inc(len); }
//Since exceptions can be thrown, class initialization can take place //if name is NULL no check for class name in .class stream has to be made. TempNewSymbol class_name = NULL; if (name != NULL) { constint str_len = (int)strlen(name); if (str_len > Symbol::max_length()) { //It's impossible to create this class; the name cannot fit //into the constant pool. THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name); } class_name = SymbolTable::new_symbol(name, str_len, CHECK_NULL); }