`

ClassLoader小结

    博客分类:
  • JVM
阅读更多

负责装载class文件;这个文件来源可能是压缩包、网络、运行时编译出的或者自动生成的class文件,jvm spec没有规定必须从什么地方加载。

 

jvm中默认提供了三种系统类加载器:

1)、启动类加载器Bootstrap ClassLoader,负责加载%JAVA_HOME%\jre\lib目录下的包,或 -Xbootclasspath 选项指定的jar包装入工作。

2)、扩展类加载器Ext ClassLoader,负责加载%JAVA_HOME%\jre\lib\ext目录下的包,或者在java.ext.dirs系统变量锁指定的路径中的所有类库

3)、应用程序类加载器App ClassLoader,负责加载用户classpath中的包

ClassLoader是双亲委派模型,除了Bootstrap ClassLoader外每个classloader都有自己的父加载器,每个加载器在加载某个类之前,先委托父加载器在其相关的目录加载,如果加载不到,则自己加载。

 

自定义类加载器加载一个类的步骤

ClassLoader 类加载逻辑分析, 以下逻辑是除 BootstrapClassLoader 外的类加载器加载流程:

 

// 检查类是否已被装载过  
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);  
     }  
}  

 

 

为什么要使用这种双亲委托模式呢?

  1. 因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
  2. 考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时被加载,所以用户自定义类是无法加载一个自定义的ClassLoader。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics