【大白话说Java面试题 第48题】【JVM篇】第8题:JVM 里的有几种 ClassLoader?为什么会有多种?
📌PDF:大白话说Java面试题 — 02-JVM篇
第8题:JVM 里的有几种 ClassLoader?为什么会有多种
📚回答:
- 核心概念:
JVM 提供了三种主要的类加载器(ClassLoader),每种类加载器负责加载不同范围的类,形成明确的职责分工。此外,多种类加载器的设计也是为了实现双亲委派模型(Parent Delegation Model)。
1. 类加载器分类
引导类加载器(Bootstrap ClassLoader):
- 负责加载 JVM 核心类库(如
rt.jar),这些类位于$JAVA_HOME/lib目录下。 - 使用原生代码实现(C++),不继承自 Java 的
ClassLoader类。
- 负责加载 JVM 核心类库(如
扩展类加载器(Extension ClassLoader):
- 负责加载 JVM 扩展类库,这些类位于
$JAVA_HOME/lib/ext目录下。 - 继承自
java.lang.ClassLoader,由 Java 实现。
- 负责加载 JVM 扩展类库,这些类位于
应用程序类加载器(Application ClassLoader):
- 负责加载用户程序的类路径(Classpath)中的类。
- 是默认的类加载器,也称为系统类加载器(System ClassLoader)。
💡代码示例:
以下代码展示了如何获取当前线程的类加载器:
publicclassClassLoaderDemo{publicstaticvoidmain(String[]args){// 获取当前类的类加载器ClassLoaderappClassLoader=ClassLoaderDemo.class.getClassLoader();System.out.println("App ClassLoader: "+appClassLoader);// 获取扩展类加载器ClassLoaderextClassLoader=appClassLoader.getParent();System.out.println("Ext ClassLoader: "+extClassLoader);// 获取引导类加载器(返回 null)ClassLoaderbootstrapClassLoader=extClassLoader.getParent();System.out.println("Bootstrap ClassLoader: "+bootstrapClassLoader);}}2. 多种类加载器的原因
职责分工:
- 每种类加载器负责加载特定范围的类,避免混乱。例如,引导类加载器加载核心类库,扩展类加载器加载拓展类库,应用程序类加载器加载用户程序类。
安全性:
- 双亲委派模型确保核心类库(如
java.lang.String)不会被用户自定义的类覆盖,从而保护 JVM 的核心功能。
- 双亲委派模型确保核心类库(如
灵活性:
- 支持开发者自定义类加载器,满足特殊需求(如动态加载类、热部署等)。
3. 双亲委派模型
定义:
- 当某个类加载器收到类加载请求时,它会优先委托父类加载器完成加载任务。如果父类加载器无法加载,则由当前类加载器尝试加载。
优点:
- 避免类的重复加载,保证核心类库的安全性。
💡面试官视角:
面试官可能会问“为什么要设计双亲委派模型?”答:为了避免类的重复加载,并保护核心类库不被篡改。
面试官可能会追问“如何打破双亲委派模型?”答:通过自定义类加载器并重写
loadClass方法,绕过父类加载器的优先级。
