来自Oracle的双亲委派机制
在Java语言中,类加载器是负责将类加载到Java虚拟机中的组件。为了避免因加载同一个类而导致重复加载的问题,Java语言采用了双亲委派机制来管理类加载器的加载顺序。本文将深入探讨来自Oracle的双亲委派机制。
双亲委派机制是一种类加载的策略,其主要思想是将类的加载顺序委托给父类加载器,从而保证Java平台的稳定和安全。在Java语言中,分为三种不同的类加载器:BootStrap ClassLoader、Extension ClassLoader和System ClassLoader,他们有不同的职责和加载优先级。
– BootStrap ClassLoader
BootStrap ClassLoader也称为启动类加载器,它是Java虚拟机的内置类加载器。它负责加载Java虚拟机核心类库,这些类库位于JRE的lib目录下。这些核心类库包括了Java API中最基本最核心的类,例如java.lang.Object、java.lang.Class等。BootStrap ClassLoader是Java中的最顶级加载器,由C++编写,因此无法使用Java代码编写。
– Extension ClassLoader
扩展类加载器(Extension ClassLoader),也称为平台类加载器,它是Java虚拟机的扩展类加载器。它负责加载Java扩展类库(EXtension),这些类库位于JRE的lib/ext目录下。当我们需要使用自定义的Java扩展类库时,需要将自己的类放置到该目录下。此时,Java虚拟机就会使用Extension ClassLoader进行加载。
– System ClassLoader
系统类加载器(System ClassLoader),也称为应用程序加载器,它是Java虚拟机的默认类加载器。它的主要目的是加载classpath下的类库。在Java应用程序中,经常会使用到System ClassLoader。
双亲委派机制的机制: 当一个类被加载时,先到父加载器去查找,如果父加载器没有找到,才会到当前加载器查找。双亲委派机制的实现依赖于ClassLoader.loadClass()方法。在双亲委派机制中,该方法会先尝试使用getParent()方法获取父类加载器来进行加载,如果父类加载器全部都不包含该类,则由当前类加载器自行加载。
双亲委托机制示例代码:
public class ClassLoaderTest {
public static void mn(String[] args)throws Exception {
System.out.println(System.getProperty(“sun.boot.class.path”));
System.out.println(System.getProperty(“java.ext.dirs”));
System.out.println(System.getProperty(“java.class.path”));
// 获取系统/应用类加载器
ClassLoader sysLoader = ClassLoader.getSystemClassLoader();
System.out.println(“系统/应用类加载器:” + sysLoader);
// 获取扩展类加载器
ClassLoader extLoader = sysLoader.getParent();
System.out.println(“扩展类加载器:” + extLoader);
// 获取Bootstrap ClassLoader,由于其是使用C++编写的,无法使用Java代码访问
ClassLoader bootstrapLoader = extLoader.getParent();
System.out.println(“启动类加载器(Bootstrap ClassLoader):” + bootstrapLoader);
}
}
运行结果如下:
/usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/classes
/usr/lib/jvm/java-8-oracle/jre/lib/ext:/usr/java/packages/lib/ext
/home/uqlea/workspace/LearningJava/bin:/usr/lib/jvm/java-8-oracle/jre/lib/ext:/usr/java/packages/lib/ext:/usr/lib/jvm/java-8-oracle/lib/ext
系统/应用类加载器:sun.misc.Launcher$AppClassLoader@1f96302a
扩展类加载器:sun.misc.Launcher$ExtClassLoader@3fa92e0f
启动类加载器(Bootstrap ClassLoader):null
从结果中可以发现,系统/应用类加载器和扩展类加载器是Java编写的,而启动类加载器是使用cpp编写的,无法访问。
双亲委派机制是Java语言中非常重要的一种机制。其可以避免Java虚拟机因为同一个类被加载多次而造成重复加载,确保Java平台的稳定和安全。理解双亲委派机制的机制和实现可以为我们更加深入地理解整个Java类加载器体系,并能更加有效地使用Java语言。