转载自 Ken Wu`s Blog!
让我们一起跟随ClassLoader里的本地方法 findBootstrapClass(), 进入jvm执行启动类加载器加载类的内部实现。
private Class findBootstrapClass0(String name)
throws ClassNotFoundException
{
check();
if (!checkName(name))
throw new ClassNotFoundException(name);
return findBootstrapClass(name);
}
private native Class findBootstrapClass(String name)
throws ClassNotFoundException;
// 摘自 j2sesrcshareclassesjavalangClassLoader.c // 表示该函数将被 java class 以jni方式调用 JNIEXPORT jclass JNICALL Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader, jstring classname) { char *clname; jclass cls = 0; char buf[128]; if (classname == NULL) { // 类名不能为空 JNU_ThrowClassNotFoundException(env, 0); return 0; } // 将java的string转成unicode字符, 如果unicode字符长度不超过128 // 则不分配内存,直接拿buf缓存来使用 // 否则就malloc一块内存存放, 如果malloc失败, 则返回NULL clname = getUTF(env, classname, buf, sizeof(buf)); if (clname == NULL) { // 类名为空, 说明 JVM 内存分配失败, 抛出邪恶的OOM. JNU_ThrowOutOfMemoryError(env, NULL); return NULL; } // 将 '.' 转换成 '/' VerifyFixClassname(clname); if (!VerifyClassname(clname, JNI_TRUE)) { // 如果指定的类名不合法, 抛出异常 JNU_ThrowClassNotFoundException(env, clname); goto done; } // 让jvm使用启动类加载器加载类, 第四位标志0表示使用启动类加载器, // throwError为JNI_FALSE时抛出 ClassNotFoundException,而JNI_TRUE抛出NoClassDefFoundError cls = JVM_FindClassFromClassLoader(env, clname, JNI_FALSE, 0, JNI_FALSE); done: if (clname != buf) { // 类名的格式有问题,且没有走buf缓存,则释放掉创建的内存, 防止内存泄漏 free(clname); } return cls; }
// 摘自 hotspotsrcsharevmprimsjvm.h /* * jvm.h头文件, 类似java接口的定义。 × 根据给定的classLoader来加载指定类 × × *env JNI运行环境 × *name 类名(路径) × init 是否需要初始化类的内部数据结构 × loader 类加载器标识 × throwError 抛出的异常类型 */ JNIEXPORT jclass JNICALL JVM_FindClassFromClassLoader(JNIEnv *env, const char *name, jboolean init, jobject loader, jboolean throwError);
// 摘自 hotspotsrcsharevmprimsjvm.cpp JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, jboolean init, jobject loader,jboolean throwError)) JVMWrapper3("JVM_FindClassFromClassLoader %s throw %s", name, throwError ? "error" : "exception"); // 确保字符串不为NULL且长度不大于 (1 << 16) -1 , 否则抛出异常 if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) { if (throwError) { THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name); } else { THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name); } } // 将类名放入一个hashmap, 标记符号用的, 并构造为 symbolHandle // (注意: Handle是一种间接的, 由线程变量分配空间的类,作用是防止GC回收) // CHECK_0是一个宏, 作用是判断是否有没有处理掉的异常, 如果有, 返回0 symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_0); // 将classLoader标识转换成JVM内部表示的数据结构, 并构造为 Handle Handle h_loader(THREAD, JNIHandles::resolve(loader)); jclass result = find_class_from_class_loader(env, h_name, init, h_loader, Handle(), throwError, thread); if (TraceClassResolution && result != NULL) { trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); } return result; JVM_END
// 摘自 hotspotsrcsharevmprimsjvm.cpp jclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) { // 生成类的内部数据结构, 核心步骤,非常复杂, 后期补充一下这里, 但是对核心逻辑没影响 klassOop klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError, CHECK_0); // 将类的数据结构, 构造为 KlassHandle KlassHandle klass_handle(THREAD, klass); if (init && klass_handle->oop_is_instance()) { // 初始化类内部的数据结构 klass_handle->initialize(CHECK_0); } // 分配内存, 生成class对象 return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror()); }