Java ClassLoader浅析
1:什么是classloader?
顾名思义,就是类加载器,就是把.class字节码文件加载到jvm里面,供程序运行。
2:classloader加载方式
a:隐式加载。这也是我们常用的加载方式,在用new创建对象时,或者类中引用其他对象时候(import),会隐式加载class到jvm中。
b:显式加载。我们在java中用到的反射机制,Class.forName(*)的形式创建类对象,反射是在使用时候加载,这里用到的是显式加载方式。
3:类加载的过程
一个class字节码文件是怎么加载到jvm中,被jvm识别并在虚拟机中初始化我们的java对象的呢?这个过程如下图:
执行顺序这是一个类加载器创建到消亡的生命周期过程,很直观。
这里链接(linking)里面又包括:验证(verifiction),准备(preparation),解析(resolution)
4:三种默认加载器
① Bootstrap classLoader(启动类加载器)
在类加载层次中最顶层的加载器,主要加载JDK中的核心类库,如:rt.jar,charSet.jar,resource.jar。这个加载器完全由JVM自己负责,我们访问不了,也控制不了。加载文件如下:
② Extention classLoader (扩展类加载器)
别名ext classLoader,加载JAVA_HOME/jre/lib/ext/目下的所有扩展的jar包。如图:
③ system classLoader(系统类加载器)
别名: App classLoader,加载应用程序classpath目录下的所有jar和class文件。一般来说,Java 应用的类都是由它来完成加载的。如图:
除了以上的三种系统默认加载器之外,用户也可以自定义加载器(customer classLoader这里我就不介绍了)。
5:双亲委派
大家都知道,在代码中用import引用指定路径的java文件, 那么这个java文件是怎么加载进来的?遇到路径和文件重名到底会加载哪个?用的什么原理呢?
在这里就要提到双亲委派的加载机制。先看下图:
加载顺序双亲委派原理,除了bootstrap加载器没有父类加载器之外,其他的加载器都有一个父类加载器,每当需要加载某个java类时,都会委派给其父类加载器去加载。
如图所示,customer classloader会委派给其父类加载器system classloader,system classloader会委派给其父类加载器Extention classloader,Extention classloader会委派给其父类加载器Bootstrap classloader,如果有则直接返回给用户需要的类
如果Bootstrap classloader没找到则让其子加载器Extention classloader加载,如果没有则返回其子加载器system classloader加载,如果没有则返回其子加载器customer classloader加载,如果还没有则直接返回ClassNotFoundException异常。
回到上面问题,如果需要加载的自定义类路径和文件和三个默认加载器里面的路劲和文件相同,那么加载的是哪个类呢?根据原理,只要在父加载器里面找到了该类就直接返回了。所以不会返回自定义里面的类。 这也是保证了加载器的安全和稳定性。