八股已死、场景当立(场景篇-JVM)
废话不多说,今天更新场景篇-JVM的知识点,做好了开始发车喽!
一、场景篇-JVM
1、Q:类加载过程与双亲委派机制?
A: 类加载过程与双亲委派机制如下:
类加载过程可以分为三个主要阶段:加载、链接和初始化。
-
加载(Loading):
- 目标:将类文件的字节码读取到内存中。
- 过程:
- 类加载器根据类名查找对应的类文件。
- 读取类文件的字节码,并将其存储在内存中。
- 创建一个与类对应的Class对象,并记录该类的全限定名、父类、接口、字段和方法等信息。
-
链接(Linking):
- 目标:将加载到内存中的类与JVM中的其他类关联起来。
- 过程:
- 验证(Verification):确保字节码符合JVM规范,防止非法操作。
- 准备(Preparation):为类的静态变量分配内存,并设置默认初始值。
- 解析(Resolution):将类中的符号引用(如类名、方法名、字段名)替换为直接引用(如内存地址)。
-
初始化(Initialization):
- 目标:执行类的静态初始化代码块,初始化静态变量。
- 过程:
- 执行类中的静态初始化块。
- 执行静态变量的赋值操作。
双亲委派机制
双亲委派机制是Java类加载器中的一种设计模式,用于确保类的加载顺序和唯一性。其核心思想是:当一个类加载器需要加载一个类时,它会先请求其父类加载器加载该类,只有当父类加载器无法加载时,才会尝试自己加载。
类加载器层次结构
Java类加载器分为以下几个层次:
-
Bootstrap ClassLoader:
- 职责:加载JVM核心类库,如java.lang.*、java.util.*等。
- 特点:由JVM实现,通常用C++编写,不继承自java.lang.ClassLoader。
-
Extension ClassLoader:
- 职责:加载JDK的扩展类库,位于jre/lib/ext目录下的类。
- 实现:通常由sun.misc.Launcher$ExtClassLoader实现。
-
Application ClassLoader:
- 职责:加载用户指定的类路径(classpath)中的类。
- 实现:通常由sun.misc.Launcher$AppClassLoader实现。
-
用户自定义类加载器:
- 职责:根据特定需求加载类,如从网络、数据库加载类。
- 实现:继承java.lang.ClassLoader,并重写findClass方法。
双亲委派机制的工作流程
-
类加载请求:
- 当一个类需要被加载时,类加载器会接收到一个加载请求。
-
请求父类加载器:
- 类加载器会首先请求其父类加载器加载该类。
-
父类加载器处理:
- 父类加载器会尝试加载该类。如果父类加载器能够加载该类(即类在父类加载器的搜索路径中),则加载完成。
-
子类加载器处理:
- 如果父类加载器无法加载该类,子类加载器才会尝试加载该类。
-
类加载完成:
- 一旦类被加载,类加载器会将该类缓存起来,以备后续使用。
双亲委派机制的优点
-
防止类的重复加载:
- 由于父类加载器优先加载类,子类加载器不会重复加载已经存在的类,节省内存和加载时间。
-
确保类的版本一致性:
- 所有类加载器共享父类加载器加载的类,确保不同类加载器加载的类具有唯一性,避免版本冲突。
-
提高安全性:
- 核心类库由Bootstrap ClassLoader加载,确保其安全性,防止恶意代码替换核心类。
双亲委派机制的实现
双亲委派机制的实现主要依赖于ClassLoader类的loadClass方法。默认情况下loadClass,
方法会先调用父类的loadClass方法,如果父类无法加载,再调用findClass方法尝试自己加载。
public class ClassLoader {protected Class<?> loadClass(String name, boolean