6.JVM类加载器的分类 -- 引导类加载器、扩展类加载器、应用程序类加载器、用户自定义类加载器

6.JVM类加载器的分类 -- 引导类加载器、扩展类加载器、应用程序类加载器、用户自定义类加载器

目录

1.类加载器分类1.1 引导类加载器(Bootstrap ClassLoader)1.2 扩展类加载器(Extension ClassLoader)1.3 应用程序类加载器(AppClassLoader或者称为系统类加载器)1.4 用户自定义类加载器(程序员自己写的)

1.类加载器分类

JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Defined ClassLoader)。 这里的自定义加载器指的不是开发人员自己定义的类加载器,而是指的所有继承自ClassLoader的类加载器。包括扩展类加载器、应用程序类加载器、用户自定义类加载器(程序员自己写的)三种。 常见的类加载器如下图所示: 第一个蓝色框表示的是引导类加载器;剩下的所有的类加载器都是自定义的类加载器。BootStrapClassLoader使用C语言实现,自定义类加载器使用Java语言实现。 注意:图中不是表示的继承关系。扩展类加载器和系统类加载器(应用程序类加载器AppClassLoader)都是继承自ClassLoader,所以将他们划分为自定义加载器。 下面的Java例子,可以帮助理解类加载器之间的关系:

public class ClassLoaderTest {

public static void main(String[] args) {

//获取系统类加载器,输出AppClassLoader,说明系统类加载器就是应用程序类加载器

ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();

System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2

//获取系统类加载器的上层:输出ExtClassLoader,说明系统类加载器的上层是扩展类加载器

ClassLoader extClassLoader = systemClassLoader.getParent();

System.out.println(extClassLoader);//sun.misc.Launcher$ExtClassLoader@1540e19d

//获取扩展类加载器的上层:输出null,获取不到引导类加载器。虽然获取不到,但是扩展类加载器的上层是引导类加载器

ClassLoader bootstrapClassLoader = extClassLoader.getParent();

System.out.println(bootstrapClassLoader);//null

//输出AppClassLoader。说明对于用户自定义类来说:默认使用系统类加载器进行加载

ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();

System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2

//打印的也是null,和获取扩展类的上层的输出是一样。可以证明String类使用引导类加载器进行加载的。扩展开来:---> Java的核心类库都是使用引导类加载器进行加载的。

ClassLoader classLoader1 = String.class.getClassLoader();

System.out.println(classLoader1);//null

}

}

1.1 引导类加载器(Bootstrap ClassLoader)

1.引导类加载器使用C/C++语言实现,在JVM内部 2.用于加载Java核心类库 3.不继承ClassLoader 4.还用于加载扩展类加载器和应用程序类加载器 5.只加载包名为java,javax,sun开头的类

1.2 扩展类加载器(Extension ClassLoader)

1.使用java语言编写,JVM自带 2.继承自ClassLoader 3.父类加载器为启动类加载器 4.从java.ext.dirs指定的路径下加载类库;或者从JDK安装目录的jre/lib/ext目录下加载类库。 5.如果用户自定义的jar包放在jre/lib/ext下,也会自动由扩展类加载器加载

1.3 应用程序类加载器(AppClassLoader或者称为系统类加载器)

1.使用jaca语言编写,JVM自带 2.继承自ClassLoader 3.父类加载器为扩展类加载器 4.负责加载环境变量classpath或系统属性java.class.path指定的类库 5.java中自己写的类都是由应用程序类加载器加载的 6.可以通过ClassLoader.getSystemClassLoader()方法获取该类加载器

理解BootstrapClassLoader、ExtClassLoader、AppClassLoader的例子:

public class ClassLoaderTest1 {

public static void main(String[] args) {

System.out.println("**********启动类加载器**************");

//获取BootstrapClassLoader能够加载的api的路径

URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs();//获取到的是通过引导类加载的类库的路径(输出参考“引导类能够加载的类库路径”)

for (URL element : urLs) {

System.out.println(element.toExternalForm());

}

//从上面的路径中随意选择一个类,来看看他的类加载器是什么:引导类加载器

ClassLoader classLoader = Provider.class.getClassLoader();

System.out.println(classLoader); //输出为null。说明是引导类加载器加载的

System.out.println("***********扩展类加载器*************");

String extDirs = System.getProperty("java.ext.dirs");

for (String path : extDirs.split(";")) {// 输出参考“扩展类能够加载的类库路径”图

System.out.println(path);

}

//从上面的路径中随意选择一个类,来看看他的类加载器是什么:扩展类加载器

ClassLoader classLoader1 = CurveDB.class.getClassLoader();

System.out.println(classLoader1);//sun.misc.Launcher$ExtClassLoader@1540e19d

}

}

引导类能够加载的类库路径:如下图。主要就是jre/lib/目录下面的jar包。 扩展类能够加载的类库路径:如下图。主要是jre/lib/ext目录以及java.ext.dirs指定的路径下的jar包

1.4 用户自定义类加载器(程序员自己写的)

除了上面3种JVM提供的类加载器之外,程序员还可以自己定义类加载器。(简单了解) 自定义加载器实现步骤: 自定义一个类加载器简单的例子:

public class CustomClassLoader extends ClassLoader { //继承ClassLoader

@Override

protected Class findClass(String name) throws ClassNotFoundException { //重载findClass方法

try {

byte[] result = getClassFromCustomPath(name);

if(result == null){

throw new FileNotFoundException();

}else{

return defineClass(name,result,0,result.length);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

}

throw new ClassNotFoundException(name);

}

private byte[] getClassFromCustomPath(String name){

//从自定义路径中加载指定类:细节略

//如果指定路径的字节码文件进行了加密,则需要在此方法中进行解密操作。(这里可以进行解密操作,防止class文件被反编译)

return null;

}

public static void main(String[] args) {

CustomClassLoader customClassLoader = new CustomClassLoader();

try {

Class clazz = Class.forName("One",true,customClassLoader);

Object obj = clazz.newInstance();

System.out.println(obj.getClass().getClassLoader());

} catch (Exception e) {

e.printStackTrace();

}

}

}

更多JVM文章请参考我的JVM专栏:https://blog.csdn.net/u011069294/category_10113093.html

相关文章

‎Drug药-真实直接交友app
bt365体育在线

‎Drug药-真实直接交友app

📅 09-07 👀 3666
60英寸等于多少厘米
怎样获得免费office365

60英寸等于多少厘米

📅 08-29 👀 994
华为阅读
365BT体育app

华为阅读

📅 10-13 👀 1360