让我们一起跟随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 (TraceCla***esolution && 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());
}
转载于:https://blog.51cto.com/aliapp/1327677