`
gogole_09
  • 浏览: 201933 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java类加载器体系结构(待续)

阅读更多
  •    JVM主要有以下的几大类加载器:

             |------Bootstrap  启动加载器

                +--- 主要负责加载 jdk/lib目录下的核心api 或者 -Xbootclasspath选项指定的jar包

             |------Extension  扩展加载器

                +--- 主要负责加载 jdk/lib/ext目录下的核心api 或者 -Djava.ext.dirs 指定目录下jar包

             |------System      系统加载器

                +--- 主要负责加载 java -classpath/-Djava.class.path所指定目录下的类

             |------Custom ClassLoader 自定义类加载器 {java.lang.ClassLoader的子类}

                +--- 程序运行期间,通过其动态加载class .

 

  • 类加载器的特性:

                |------每个Classloader都维护一份自己的名称空间,同一个空间中,不能出现两个同名的类。

                |------Java类加载器采用“双亲委托的加载机制”

 

  下面,我们来看一个自定义类加载器的处理流程:

  

 以下代码,演示除了bootstarp加载器外的类加载器加载流程:

   

// 检查类是否已被装载过
Class c = findLoadedClass(name);
if (c == null ) {
     // 指定类未被装载过
     try {
         if (parent != null ) {
             // 如果父类加载器不为空, 则委派给父类加载
             c = parent.loadClass(name, false );
         } else {
             // 如果父类加载器为空, 则委派给启动类加载加载
             c = findBootstrapClass0(name);
         }
     } catch (ClassNotFoundException e) {
         // 启动类加载器或父类加载器抛出异常后, 当前类加载器将其
         // 捕获, 并通过findClass方法, 由自身加载
         c = findClass(name);
     }
}

 

        

利用Class.forName来加载类,Class.forName使用的是被调用者的类加载器来加载类的.

    这种特性,证明了java类加载器中的名称是唯一的,不会互相干扰,既在一般环境中,保证同一类与之关联的其他类都是通过当前类的类加载器所加载的。

 

public static Class forName(String className)
     throws ClassNotFoundException {
     return forName0(className, true , ClassLoader.getCallerClassLoader());
//getCallerClassLoader() 就是得到调用当前forName方法的类的类加载器
}

/** Called after security checks have been made. */
private static native Class forName0(String name, boolean initialize,
ClassLoader loader)
     throws ClassNotFoundException;

 

 线程上下文类加载器:

      Java默认的线程上下文类加载器是 系统类加载器(AppClassLoader)

   

// Now create the class loader to use to launch the application
try {
    loader = AppClassLoader.getAppClassLoader(extcl);
} catch (IOException e) {
    throw new InternalError(
"Could not create application class loader" );
}

// Also set the context class loader for the primordial thread.
Thread.currentThread().setContextClassLoader(loader);

 

 

     在sun.misc.Launch的无参构造函数Launch()中定义了上述代码。

     使用线程上下文加载器,可以在执行线程中,抛弃双亲委托加载链模式,使用线程上下文里的类加载器加载类。

      如: 在线程上下文中加载第三方的JNDI实现,而不依赖于双亲委托。

 

 自定义类加载器:

    

  • 大小: 96.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics