Java三个类加载器及它们的相互关系
⽬录
⼀、什么是类加载器?
⼆、AppClassLoader系统类加载器
三、ExtClassLoader扩展类加载器
四、BootstrapClassLoader启动类加载器
java源代码加密
五、加载器关系总结
六、参考资料
⼀、什么是类加载器?
虚拟机设计团队把类加载阶段中的“通过⼀个类的全限定名来获取描述此类的⼆进制字节流”这个动作放到Java虚拟机外部去实现,以便让应⽤程序⾃⼰决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”
类加载器可以说是Java语⾔的⼀项创新,也是Java语⾔流⾏的重要原因之⼀,它最初是为了满⾜Java Applet的需求⽽开发出来的。虽然⽬前Java Applet技术基本上已经“死掉”,但类加载器却在类层次划分、OSGi、热部署、代码加密等领域⼤放异彩,成为了Java技术体系中⼀块重要的基⽯,可谓是失之桑榆,收之东隅。
类加载器虽然只⽤于实现类的加载动作,但它在Java程序中起到的作⽤却远远不限于类加载阶段。对于任意⼀个类,都需要由加载它的类加载器和这个类本⾝⼀同确⽴其在Java虚拟机中的唯⼀性,每⼀个类,都拥有⼀个独⽴的类名称空间。这句话可以表达得更通俗⼀些:⽐较两个类是否“相等”,只有在这两个类是由同⼀个类加载器加载的前提下才有意义。否则,即使这两个类来源于同⼀个Class⽂件,被同⼀个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。
⼆、AppClassLoader系统类加载器
AppClassLoader应⽤类加载器,⼜称为系统类加载器,负责在JVM启动时,加载来⾃命令java中的classpath或者java.class.path系统属性或者CLASSPATH操作系统属性所指定的JAR类包和类路径
获取当前类的类加载器:
public class AppClassLoaderTest {
public static void main(String[] args) {
System.out.SystemClassLoader());
}
}
输出:
sun.misc.Launcher$AppClassLoader@73d16e93
这说明AppclassLoader是当前应⽤classpath所有类的加载器。
查看ClassLoader的源码可发现:在没有特定说明的情况下,⽤户⾃定义的任何类加载器都将该类加载器作为⾃定义类加载器的⽗加载器.
通过执⾏下⾯的代码即可获得classpath的加载路径:
String classPath = Property("java.class.path");
for (String path : classPath.split(";")) {
System.out.println(path);
}
输出:
.
通常是当前执⾏字节码的路径。
main函数的类的加载就是使⽤AppClassLoader加载器进⾏加载的,⽽AppClassLoader的⽗加载器是ExtClassLoader: public class AppClassLoaderTest {
public static void main(String[] args) {
ClassLoader classLoader = ClassLoader();
System.out.println(classLoader);
System.out.Parent());
}
private static class Test {
}
}
输出:
sun.misc.Launcher$AppClassLoader@73d16e93
sun.misc.Launcher$ExtClassLoader@15db9742
三、ExtClassLoader扩展类加载器
ExtClassLoader称为扩展类加载器,主要负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/⽬录下的所有jar包或者由dirs系统属性指定的jar包.放⼊这个⽬录下的jar包对AppClassLoader加载器都是可见的(因为ExtClassLoader是AppClassLoader的⽗加载器,并且Java类加载器采⽤了委托机制).
ExtClassLoader的类扫描路径通过执⾏下⾯代码来看⼀下:
public class ExtClassLoaderTest {
public static void main(String[] args) {
String extDirs = Property("dirs");
for (String path : extDirs.split(";")) {
System.out.println(path);
}
}
}
执⾏结果如下:
D:\TOOLS\JAVA\lib\ext
C:\WINDOWS\Sun\Java\lib\ext
从上⾯的路径中随意选择⼀个类,来看看它的类加载器是什么:
public class ExtClassLoaderTest {
public static void main(String[] args) {
ClassLoader classLoader = ClassLoader();
System.out.println(classLoader);
System.out.Parent());
}
}
输出:
sun.misc.Launcher$ExtClassLoader@30f39991
null
从输出结果可知ExtClassLoader的⽗加载器为null
四、BootstrapClassLoader启动类加载器
启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核⼼类库,如:rt.jar、resources.jar、charsets.jar 等
通过如下程序获得该类加载器从哪些地⽅加载了相关的jar或class⽂件:
import java.URL;
public class BootstraplassLoaderPath {
public static void main(String[] args) {
URL[] urLs = sun.BootstrapClassPath().getURLs();
for (URL url : urLs) {
System.out.ExternalForm());
}
}
}
输出:
file:/D:/TOOLS/JAVA/lib/resources.jar
file:/D:/TOOLS/JAVA/lib/rt.jar
file:/D:/TOOLS/JAVA/lib/sunrsasign.jar
file:/D:/TOOLS/JAVA/lib/jsse.jar
file:/D:/TOOLS/JAVA/lib/jce.jar
file:/D:/TOOLS/JAVA/lib/charsets.jar
file:/D:/TOOLS/JAVA/lib/jfr.jar
file:/D:/TOOLS/JAVA/classes
从rt.jar中选择String类,看⼀下String类的类加载器是什么:
public class stringBootstraplassLoaderTest {
public static void main(String[] args) {
ClassLoader classLoader = ClassLoader();
System.out.println(classLoader);
}
}
输出:
null
由于BootstrapClassLoader对Java不可见,所以返回了null,我们也可以通过某⼀个类的加载器是否为null来作为判断该类是不是使⽤BootstrapClassLoader进⾏加载的依据。
另外上⾯提到ExtClassLoader的⽗加载器返回的是null,那是否说明ExtClassLoader的⽗加载器是BootstrapClassLoader. Bootstrap ClassLoader是由C/C++编写的,它本⾝是虚拟机的⼀部分,所以它并不是⼀个JAVA类,也就是⽆法在java代码中
获取它的引⽤,JVM启动时通过Bootstrap类加载器加载rt.jar等核⼼jar包中的class⽂件,之前的int.class,String.class都是由它加载。
五、加载器关系总结
JVM初始化sun.misc.Launcher并创建Extension ClassLoader和AppClassLoader实例。并将ExtClassLoader设置为AppClassLoader的⽗加载器,Bootstrap则是ExtClassLoader的⽗加载器.
关系图如下:
六、参考资料
1.
2.
到此这篇关于Java三个类加载器及它们的相互关系的⽂章就介绍到这了,更多相关Java类加载器内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。