我们知道JVM加载类的过程遵循“双亲委派机制”,每当JVM启动时,是通过一个ClassLoader来加载class文件的。
ClassLoader有三个实现,分别是:BootstrapLoader,ExtClassLoader和AppClassLoader.
三个类加载器的作用不同,所加载的class文件也不相同。
下面我们通过代码实现查看三个类加载器分别所加载的class路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/** * * @author JJ_knows * */ public class ClassLoaderTest { public static void main(String[] args) { System.out.println("启动类加载器加载的类:"); String bootPath = System.getProperty("sun.boot.class.path");//启动类加载器所加载的是JVM中最底层的类,加载时的搜索路径是sun.boot.class.path。 System.out.println(bootPath.replaceAll(";",System.lineSeparator())); System.out.println("......................"); System.out.println("扩展类加载器加载的类:"); String extPath = System.getProperty("java.ext.dirs");//扩展类加载器是用来加载java的一些库的,加载时的搜索路径是java.ext.dirs System.out.println(extPath.replaceAll(";",System.lineSeparator())); System.out.println("......................"); System.out.println("应用类加载器加载的类:"); String appPath = System.getProperty("java.class.path");//应用类加载器搜索路径是java.class.path System.out.println(appPath.replaceAll(";",System.lineSeparator())); } }
输出结果:
启动类加载器加载的类:
D:jdk8Javajdk1.8.0_162jrelibresources.jar
D:jdk8Javajdk1.8.0_162jrelibrt.jar
D:jdk8Javajdk1.8.0_162jrelibsunrsasign.jar
D:jdk8Javajdk1.8.0_162jrelibjsse.jar
D:jdk8Javajdk1.8.0_162jrelibjce.jar
D:jdk8Javajdk1.8.0_162jrelibcharsets.jar
D:jdk8Javajdk1.8.0_162jrelibjfr.jar
D:jdk8Javajdk1.8.0_162jreclasses
......................
扩展类加载器加载的类:
D:jdk8Javajdk1.8.0_162jrelibext
C:WindowsSunJavalibext
......................
应用类加载器加载的类:
D:jdk8Javajdk1.8.0_162jrelibresources.jar
D:jdk8Javajdk1.8.0_162jrelibrt.jar
D:personalreadTemplateDemolbgw-webtargettest-classes
D:personalreadTemplateDemolbgw-webtargetclasses
D:repositoryorgapachelogginglog4jlog4j-api2.7log4j-api-2.7.jar
D:repositoryorgapachelogginglog4jlog4j-core2.7log4j-core-2.7.jar
D:ideaIU-2017.2.winlibidea_rt.jar
双亲委派机制的加载过程是如何实现的呢?
ClassLoader中有一个 loadClass()方法,我们进入这个方法查看:
我们可以看到加载类时,首先通过:应用类加载器->扩展类加载器->启动类加载器的顺序 ,从下到上的依次进行检查,看是否已经被加载。如果已经被加载,则直接返回。
如果并未被加载过:
1ExtClassLoader 和AppClassLoader 等类加载器,通过重写这个findClass()方法,实现对不同路径下的类进行加载。
由此可知,当我们自定义类加载器的时候,只需继承ClassLoader并重写这个方法即可。
(注意这里采用的设计模式: 模板方法。)
为何要采用双亲委派机制,它的作用是什么呢?
1. 避免了重复加载
2.出于安全考虑,保证了java核心类不被篡改。
那可不可以打破“双亲委派机制”?如何打破?
很简单,只需要重写loadClass()方法就可以了。
最后
以上就是无辜绿茶最近收集整理的关于类加载的过程中,不同类加载器的加载路径测试的全部内容,更多相关类加载内容请搜索靠谱客的其他文章。
发表评论 取消回复