「JVM 类加载子系统」系列文章
加载阶段需要完成的一个核心任务:「通过一个类的全限定名来获取定义此类的二进制字节流」
Java 虚拟机设计团队有意将这一任务放到 Java 虚拟机外部,以便让应用程序自己去决定如何获取所需的类
实现这个任务的代码就被作:类加载器
类加载器虽然只用于完成实现类的加载动作,但它在 Java 程序中起到的作用却远超类加载阶段
每个 Class 对象都有一个方法:getClassLoader()
。顾名思义,获取加载该 Class 对象的类加载器
对于任意一个类,都必须由它的类加载器和这个类本身一起共同确定它在 Java 虚拟机中的唯一性
更通俗一点:比较两个类是否「相等」,只有在这两个类是由同一个类加载器加载的前提下才有意义;否则,即使这两个类来源同一个 Class 文件,被同一个 Java 虚拟机加载,只要加载它们的类加载器不同,那么这两个类就必定不相等
从 Java 虚拟机的角度,只有两种不同的类加载器:
java.lang.ClassLoader
从 Java 开发人员的角度,类加载器的划分更细致一些:
启动类加载器 (Bootstrap ClassLoader):负责加载存放在<JAVA_HOME>/lib
目录,或者被-Xbootclasspath
参数所指定的路径中存放的,而且可以被 JVM 识别的类库加载到虚拟机内存中
rt.jar
、tools.jar
,名字不符合的类库即使放在lib
目录中也不会被加载扩展类加载器 (Extension ClassLoader):负责加载存放在<JAVA_HOME>/lib/ext
目录,或者被java.ext.dirs
系统变量所指定的路径中所有的类库
sun.misc.Launcher$ExtClassLoader
中以 Java 代码的形式实现应用程序类加载器 (Application ClassLoader):负责加载用户类路径 (ClassPath) 上所有的类库
sun.misc.Launcher$ClassLoader
中以 Java 代码的形式实现它们三者的关系如下:(增加了一个自定义类加载器)
xxxxxxxxxx
public static void main(String[] args) {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
System.out.println(systemClassLoader.getParent());
System.out.println(systemClassLoader.getParent().getParent());
}
// result
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
null
由于启动类加载器是由 C++ 实现,所以只会输出一个null
关于三者的源码分析可见 剖析 [Bootstrap、Extension、Application] ClassLoader
下面可以更具体的输出一下每个类加载器加载的类库
public static void main(String[] args) {
System.out.println("---- 启动类加载器加载的文件 ----");
URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
for (URL urL : urLs) {
System.out.println(urL);
}
System.out.println("---- 扩展类加载器加载的文件 ----");
System.out.println(System.getProperty("java.ext.dirs"));
System.out.println("---- 应用程序类加载器加载的文件 ----");
System.out.println(System.getProperty("java.class.path"));
}
---- 启动类加载器加载的文件 ----
file:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/sunrsasign.jar
file:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/cat.jar
file:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/classes
---- 扩展类加载器加载的文件 ----
/Users/lfool/Library/Java/Extensions:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext:
/Library/Java/Extensions:
/Network/Library/Java/Extensions:
/System/Library/Java/Extensions:
/usr/lib/java
---- 应用程序类加载器加载的文件 ----
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/cat.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/charsets.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/crs-agent.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/dnsns.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/jaccess.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/legacy8ujsse.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/localedata.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/nashorn.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/openjsse.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/sunec.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/zipfs.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jce.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jfr.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jsse.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/management-agent.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/resources.jar:
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/rt.jar:
/Users/lfool/myself/IdeaProjects/concurrency/target/classes:
/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar