论坛首页 Java版 企业应用

重温java之bootstrap类加载原理(scsl2.3+jdk1.5)

浏览 1166 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2007-10-31 关键字: bootstrap classloader jvm
让我们一起跟随ClassLoader里的本地方法 findBootstrapClass(), 进入jvm执行启动类加载器加载类的内部实现。
java 代码
 
  1. private Class findBootstrapClass0(String name)  
  2.     throws ClassNotFoundException  
  3.     {  
  4.     check();  
  5.     if (!checkName(name))  
  6.         throw new ClassNotFoundException(name);  
  7.     return findBootstrapClass(name);  
  8.     }  
  9.   
  10.     private native Class findBootstrapClass(String name)  
  11.     throws ClassNotFoundException;  


cpp 代码
  1. // 摘自 j2se\src\share\classes\java\lang\ClassLoader.c
  2. // 表示该函数将被 java class 以jni方式调用
  3. JNIEXPORT jclass JNICALL
  4. Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader,
  5. jstring classname)
  6. {
  7.     char *clname;
  8.     jclass cls = 0;
  9.     char buf[128];

  10.     if (classname == NULL) {
  11.         // 类名不能为空
  12.         JNU_ThrowClassNotFoundException(env, 0);
  13.         return 0;
  14.     }

  15.     // 将java的string转成unicode字符, 如果unicode字符长度不超过128
  16.     // 则不分配内存,直接拿buf缓存来使用
  17.     // 否则就malloc一块内存存放, 如果malloc失败, 则返回NULL
  18.     clname = getUTF(env, classname, buf, sizeof(buf));
  19.     if (clname == NULL) {
  20.        // 类名为空, 说明 JVM 内存分配失败, 抛出邪恶的OOM.
  21.        JNU_ThrowOutOfMemoryError(env, NULL);
  22.        return NULL;
  23.     }

  24.     // 将 '.' 转换成 '/'
  25.     VerifyFixClassname(clname);

  26.     if (!VerifyClassname(clname, JNI_TRUE)) {
  27.       // 如果指定的类名不合法, 抛出异常
  28.       JNU_ThrowClassNotFoundException(env, clname);
  29.       goto done;
  30.     }

  31.     // 让jvm使用启动类加载器加载类, 第四位标志0表示使用启动类加载器,
  32.     // throwError为JNI_FALSE时抛出 ClassNotFoundException,而JNI_TRUE抛出NoClassDefFoundError
  33.     cls = JVM_FindClassFromClassLoader(env, clname, JNI_FALSE, 0, JNI_FALSE);

  34. done:
  35.     if (clname != buf) {
  36.        // 类名的格式有问题,且没有走buf缓存,则释放掉创建的内存, 防止内存泄漏
  37.        free(clname);
  38.     }

  39.     return cls;
  40. }


cpp 代码
  1. // 摘自 hotspot\src\share\vm\prims\jvm.h
  2. /*
  3. * jvm.h头文件, 类似java接口的定义。
  4. × 根据给定的classLoader来加载指定类
  5. ×
  6. × *env JNI运行环境
  7. × *name 类名(路径)
  8. × init 是否需要初始化类的内部数据结构
  9. × loader 类加载器标识
  10. × throwError 抛出的异常类型
  11. */
  12. JNIEXPORT jclass JNICALL
  13. JVM_FindClassFromClassLoader(JNIEnv *env, const char *name, jboolean init,
  14. jobject loader, jboolean throwError);



cpp 代码
  1. // 摘自 hotspot\src\share\vm\prims\jvm.cpp
  2. JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name,
  3.      jboolean init, jobject loader,jboolean throwError))

  4. JVMWrapper3("JVM_FindClassFromClassLoader %s throw %s", name,
  5. throwError ? "error" : "exception");

  6. // 确保字符串不为NULL且长度不大于 (1 << 16) -1 , 否则抛出异常
  7. if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
  8.     if (throwError) {
  9.        THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
  10.     } else {
  11.        THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name);
  12.     }
  13. }

  14. // 将类名放入一个hashmap, 标记符号用的, 并构造为 symbolHandle
  15. // (注意: Handle是一种间接的, 由线程变量分配空间的类,作用是防止GC回收)
  16. // CHECK_0是一个宏, 作用是判断是否有没有处理掉的异常, 如果有, 返回0
  17. symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_0);

  18. // 将classLoader标识转换成JVM内部表示的数据结构, 并构造为 Handle
  19. Handle h_loader(THREAD, JNIHandles::resolve(loader));

  20. jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
  21. Handle(), throwError, thread);

  22. if (TraceClassResolution && result != NULL) {
  23.  trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result)));
  24. }

  25. return result;
  26. JVM_END


cpp 代码
  1. // 摘自 hotspot\src\share\vm\prims\jvm.cpp
  2. jclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) {

  3. // 生成类的内部数据结构, 核心步骤,非常复杂, 后期补充一下这里, 但是对核心逻辑没影响
  4. klassOop klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError, CHECK_0);

  5. // 将类的数据结构, 构造为 KlassHandle
  6. KlassHandle klass_handle(THREAD, klass);

  7. if (init && klass_handle->oop_is_instance()) {
  8. // 初始化类内部的数据结构
  9. klass_handle->initialize(CHECK_0);
  10. }

  11. // 分配内存, 生成class对象
  12. return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror());
  13. }
   
最后更新时间:2008-07-28
galaxystar 写道
让我们一起跟随ClassLoader里的本地方法 findBootstrapClass(), 进入jvm执行启动类加载器加载类的内部实现。
java 代码
 
  1. private Class findBootstrapClass0(String name)  
  2.     throws ClassNotFoundException  
  3.     {  
  4.     check();  
  5.     if (!checkName(name))  
  6.         throw new ClassNotFoundException(name);  
  7.     return findBootstrapClass(name);  
  8.     }  
  9.   
  10.     private native Class findBootstrapClass(String name)  
  11.     throws ClassNotFoundException;  


cpp 代码
  1. // 摘自 j2se\src\share\classes\java\lang\ClassLoader.c
  2. // 表示该函数将被 java class 以jni方式调用
  3. JNIEXPORT jclass JNICALL
  4. Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader,
  5. jstring classname)
  6. {
  7.     char *clname;
  8.     jclass cls = 0;
  9.     char buf[128];

  10.     if (classname == NULL) {
  11.         // 类名不能为空
  12.         JNU_ThrowClassNotFoundException(env, 0);
  13.         return 0;
  14.     }

  15.     // 将java的string转成unicode字符, 如果unicode字符长度不超过128
  16.     // 则不分配内存,直接拿buf缓存来使用
  17.     // 否则就malloc一块内存存放, 如果malloc失败, 则返回NULL
  18.     clname = getUTF(env, classname, buf, sizeof(buf));
  19.     if (clname == NULL) {
  20.        // 类名为空, 说明 JVM 内存分配失败, 抛出邪恶的OOM.
  21.        JNU_ThrowOutOfMemoryError(env, NULL);
  22.        return NULL;
  23.     }

  24.     // 将 '.' 转换成 '/'
  25.     VerifyFixClassname(clname);

  26.     if (!VerifyClassname(clname, JNI_TRUE)) {
  27.       // 如果指定的类名不合法, 抛出异常
  28.       JNU_ThrowClassNotFoundException(env, clname);
  29.       goto done;
  30.     }

  31.     // 让jvm使用启动类加载器加载类, 第四位标志0表示使用启动类加载器,
  32.     // throwError为JNI_FALSE时抛出 ClassNotFoundException,而JNI_TRUE抛出NoClassDefFoundError
  33.     cls = JVM_FindClassFromClassLoader(env, clname, JNI_FALSE, 0, JNI_FALSE);

  34. done:
  35.     if (clname != buf) {
  36.        // 类名的格式有问题,且没有走buf缓存,则释放掉创建的内存, 防止内存泄漏
  37.        free(clname);
  38.     }

  39.     return cls;
  40. }


cpp 代码
  1. // 摘自 hotspot\src\share\vm\prims\jvm.h
  2. /*
  3. * jvm.h头文件, 类似java接口的定义。
  4. × 根据给定的classLoader来加载指定类
  5. ×
  6. × *env JNI运行环境
  7. × *name 类名(路径)
  8. × init 是否需要初始化类的内部数据结构
  9. × loader 类加载器标识
  10. × throwError 抛出的异常类型
  11. */
  12. JNIEXPORT jclass JNICALL
  13. JVM_FindClassFromClassLoader(JNIEnv *env, const char *name, jboolean init,
  14. jobject loader, jboolean throwError);



cpp 代码
  1. // 摘自 hotspot\src\share\vm\prims\jvm.cpp
  2. JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name,
  3.      jboolean init, jobject loader,jboolean throwError))

  4. JVMWrapper3("JVM_FindClassFromClassLoader %s throw %s", name,
  5. throwError ? "error" : "exception");

  6. // 确保字符串不为NULL且长度不大于 (1 << 16) -1 , 否则抛出异常
  7. if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
  8.     if (throwError) {
  9.        THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
  10.     } else {
  11.        THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name);
  12.     }
  13. }

  14. // 将类名放入一个hashmap, 标记符号用的, 并构造为 symbolHandle
  15. // (注意: Handle是一种间接的, 由线程变量分配空间的类,作用是防止GC回收)
  16. // CHECK_0是一个宏, 作用是判断是否有没有处理掉的异常, 如果有, 返回0
  17. symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_0);

  18. // 将classLoader标识转换成JVM内部表示的数据结构, 并构造为 Handle
  19. Handle h_loader(THREAD, JNIHandles::resolve(loader));

  20. jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
  21. Handle(), throwError, thread);

  22. if (TraceClassResolution && result != NULL) {
  23.  trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result)));
  24. }

  25. return result;
  26. JVM_END


cpp 代码
  1. // 摘自 hotspot\src\share\vm\prims\jvm.cpp
  2. jclass find_class_from_class_loader(JNIEnv* env, symbolHandle name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) {

  3. // 生成类的内部数据结构, 核心步骤,非常复杂, 后期补充一下这里, 但是对核心逻辑没影响
  4. klassOop klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError, CHECK_0);

  5. // 将类的数据结构, 构造为 KlassHandle
  6. KlassHandle klass_handle(THREAD, klass);

  7. if (init && klass_handle->oop_is_instance()) {
  8. // 初始化类内部的数据结构
  9. klass_handle->initialize(CHECK_0);
  10. }

  11. // 分配内存, 生成class对象
  12. return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror());
  13. }

 

   
0 请登录后投票
论坛首页 Java版 企业应用

跳转论坛:
JavaEye推荐