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