JVM双亲委派模型

双亲委派模型:向上询问 向下委派

Java虚拟机对class文件采用的是按需加载的方式(也可以称之为懒加载),也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象.并且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式(类似带孩子),如下图示:

基于双亲委派模型进行类的加载,其具体过程如下:
1) 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委 托给父类的加载器去执行;
2) 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将 到达顶层的启动类加载器(使用 C/C++去实现的类加载器);
3) 如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加 载任务,子加载器才会尝试自己去加载,这就是双亲委派模式;
4) 父类加载器一层一层往下分配任务,如果子类加载器能加载,则加载此类,如果将 加载任务分配至系统类加载器也无法加载此类,则抛出异常。 具体代码我们可以参考 ClassLoader#loadClass 方法的具体实现,例如:
protected Class<?> loadClass(String name, boolean resolve)
     throws ClassNotFoundException
{
     synchronized (getClassLoadingLock(name)) {
     // First, check if the class has already been loaded
     Class<?> c = findLoadedClass(name);
     if (c == null) {
         long t0 = System.nanoTime();
         try {
             if (parent != null) {
                 c = parent.loadClass(name, false);
             } else {
                 c = findBootstrapClassOrNull(name);
             }
         } catch (ClassNotFoundException e) {
             // ClassNotFoundException thrown if class not found
             // from the non-null parent class loader
         }
     if (c == null) {
        // If still not found, then invoke findClass in order
         // to find the class.
             long t1 = System.nanoTime();
             c = findClass(name);
             // this is the defining class loader; record the stats
             sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 
                - t0);
 
             sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
             sun.misc.PerfCounter.getFindClasses().increment();
         }
      }
     if (resolve) {
         resolveClass(c);
     }
     return c;
   } 
}
其中,如上代码的loadClass方法内部调用了findLoadedClass,此时会:
1)调用AppClassLoader对象的相关方法,检查此对象缓存中是否已经加载过此类,如果已经加载过则直接返回类的字节码对象
2)如果AppClassLoader缓存中不存在,则会调用ExtClassLoade对象的相关方法,检查其对象缓存是否存在,假如存在则直接返回类的字节码对象
3)如果ExtClassLoader对象的缓存中不存在,则调用BootStrapClassLoader对象中的相关方法,检查其对象缓存中是否存在,存在此对象则直接返回
4)如果BootStrapClassLoader对象中缓存不存在,则会从BootStrapClassLoader的类搜索路径下进行类文件的查找,一般是rt.jar,如果找不到底层会抛出ClassNotFoundException
5)ExtClassLoader会捕捉ClassNotFoundException,然后从ExtClassLoader的类搜索路径下进行类文件的查找,如果也找不到则会抛出ClassNotFoundException
6)AppClassLoader会捕捉ClassNotFoundException,然后从AppClassLoader的类搜索路径下进行类文件的查找(这里的路径一般为classpath),如果找到了则将类读入字节数组,并调用AppClassLoader的defineClass方法,创建类的字节码对象,如果找不到则抛出ClassNotFoundException

基于这种双亲委派机制实现了类加载时的优先级层次关系,同时也可以保证同一个类只 被一个加载器加载(例如 Object 类只会被 BootstrapClassLoader 加载),这样更有利于 java 程序的稳定运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值