一、知识点汇总
JVM是Java运行基础,卖你是是一定对遇到JVM的相关问题,内容相对集中,但是知识深度要求较高
其中内存模型,类加载机制,GC是重点。性能调优方面更偏向于应用,重点突出实践能力。编译器优化和执行模式偏向于理论基础,重点掌握知识点。
需了解:
二、知识点详解:
1.JVM内存模型:
1.1 栈
1.2 本地方法栈
1.3 程序计数器
1.4 堆
1.5 方法区
2. 类加载
2.1 类加载器
1. 启动类加载器(Bootstrap ClassLoader)
- 职责:加载 Java 核心类库,如java.lang.*、java.util.*等。
- 实现:由本地代码(通常是 C++)实现,不是java.lang.ClassLoader的子类。
- 加载路径:$JAVA_HOME/jre/lib/rt.jar或jrt:/modules(在模块化系统中)。
- 特点:是所有类加载器的顶层,没有父类加载器。
2. 扩展类加载器(Extension ClassLoader)
- 职责:加载扩展库中的类。
- 实现:由sun.misc.Launcher$ExtClassLoader实现,是java.lang.ClassLoader的子类。
- 加载路径:$JAVA_HOME/jre/lib/ext目录或由java.ext.dirs系统属性指定的目录。
- 父类加载器:引导类加载器。
3. 应用程序类加载器(Application ClassLoader)
- 职责:加载应用程序类路径(classpath)中的类。
- 实现:由sun.misc.Launcher$AppClassLoader实现,是java.lang.ClassLoader的子类。
- 加载路径:由java.class.path系统属性指定的目录和 JAR 文件。
- 父类加载器:扩展类加载器。
4. 自定义类加载器(Custom ClassLoader)
- 职责:满足特定需求的类加载器,通常在应用程序中自定义实现。
- 实现:继承java.lang.ClassLoader并重写findClass方法。
- 加载路径:由开发者自行定义,可以是文件系统、网络、数据库等。
- 父类加载器:可以指定,也可以继承应用程序类加载器。
2.2 双亲委派机制
- 启动类加载器(Bootstrap ClassLoader):负责加载 Java 核心库(位于JAVA_HOME/lib目录下的类库,如rt.jar)。
- 扩展类加载器(Extension ClassLoader):负责加载 Java 扩展库(位JAVA_HOME/lib/ext目录下的类库)。
- 应用程序类加载器(Application ClassLoader):负责加载应用程序类路径(classpath上的类。
具体流程为:
- 当前类加载器收到类加载请求:当一个类加载器收到加载类的请求时,它不会立即尝试加载该类。
- 将请求委派给父类加载器:当前类加载器首先将加载请求委派给父类加载器。
- 父类加载器处理请求:
- 如果父类加载器存在,则父类加载器会继续将请求向上委派,直到到达启动类加载器。
- 启动类加载器尝试加载类,如果成功,则返回类的引用。
- 父类加载器无法加载类:如果启动类加载器无法加载该类,加载失败返回到子类加载器。
- 当前类加载器尝试加载类:如果父类加载器无法加载该类,则由当前类加载器尝试加载。
3. JVM的垃圾回收机制
3.1 垃圾回收机制是什么?
所谓垃圾回收机制(Garbage Collection, 简称GC),指自动管理动态分配的内存空间的机制,自动回收不再使用的内存,不定时去堆内存中清理不可达对象,以避免内存泄漏和内存溢出的问题。最早是在1960年代提出的。
垃圾回收是 java相较于c、c++语言的优势之一。其他编程语言,如C#、Python和Ruby等,也都提供了垃圾回收机制。不可达的对象并不会马上就会直接回收, 垃圾收集器在一个Java程序中的执行是自动的,不能强制执行,程序员唯一能做的就是通过调用System.gc 方法来建议执行垃圾收集器,但其是否可以执行,什么时候执行却都是不可知的。
这也是垃圾收集器的最主要的缺点。
3.2垃圾回收流程
1. 垃圾分类
首先我们的 jvm 在进行垃圾回收的过程,需要确定哪些对象是垃圾对象,哪些对象是存活对象。
一般有三种常用算法可以将对象分类:
1.引用计数法:
引用计数法(Reference Counting)是一种内存管理技术,用于跟踪对象的引用数量。每个对象都有一个引用计数器,记录着指向该对象的引用数量。当一个对象被引用时,引用计数器加一;当一个引用被释放时,引用计数器减一。当引用计数器为零时,表示没有任何引用指向该对象,该对象可以被释放,回收其占用的内存。
2.可达性分析法:
可达性分析算法是JVM垃圾回收中的一种算法,它通过分析对象的引用关系,判断对象是否可达,从而决定对象是否可以被回收。
3.三色标记算法(并行环境)
三色标记算法是一种用于垃圾回收的标记算法,通过将对象分为三种颜色(白色、灰色和黑色)来管理垃圾收集过程。它主要解决了在并发垃圾收集过程中如何正确标记存活对象的问题,避免了遗漏存活对象或错误标记对象的情况。
3.对比
引用计数法通过维护引用计数器来跟踪对象的引用数量,具有实时性好、简单高效等优点,但存在循环引用等问题;而可达性分析法则通过分析对象的引用关系来判断对象是否可达,从而决定对象是否可以被回收,具有准确性高、效率好等优点,是JVM中常用的垃圾回收算法之一。
2.垃圾查找及垃圾清理
当程序运行时达到一定条件就会触发特定的垃圾回收算法,垃圾收集器会将所有的被标记过的不可达对象清理。
常用的垃圾回收算法:
1. 标记-清除算法
- 原理:垃圾收集器首先遍历对象图,标记所有可达的对象,然后清除未标记的对象。
- 优点:简单直接,不需要移动对象。
- 缺点:会产生内存碎片,可能导致大对象分配失败。
2. 标记-压缩算法
- 原理:在标记阶段标记所有可达的对象后,压缩阶段将存活的对象移动到内存的一端,整理出连续的可用内存空间。
- 优点:消除了内存碎片问题。
- 缺点:对象移动需要额外的时间和资源。
3. 复制算法
- 原理:将内存分为两个相等的区域,每次只使用其中一个。当这个区域使用完时,将存活的对象复制到另一个区域,然后清空当前区域。
- 优点:简单高效,没有内存碎片问题。
- 缺点:需要双倍的内存空间。
4. 分代收集算法
- 原理:根据对象的生命周期将堆内存划分为几代(通常是新生代和老年代),新生代使用复制算法,老年代使用标记-压缩或标记-清除算法。
- 优点:优化了垃圾收集性能,因为大部分对象在新生代被收集,减少了老年代的垃圾收集频率。
- 缺点:需要额外的内存管理和调优。
5. 分区算法
- 原理:将堆内存划分为多个小的独立区域(Region),每个区域可以独立进行垃圾收集。
- 优点:提高了内存管理的灵活性和效率,适用于大堆内存的应用。
- 缺点:实现较复杂,需要精细的内存管理。
6. 并行和并发收集算法
- 并行收集:垃圾收集过程由多个线程并行执行,提高了垃圾收集的效率。
- 并发收集:垃圾收集过程与应用线程并发执行,减少了应用停顿时间。
具体垃圾收集器使用的算法
- Serial GC:使用标记-压缩算法。
- Parallel GC:新生代使用复制算法,老年代使用标记-压缩算法。
- CMS GC:新生代使用复制算法,老年代使用标记-清除算法,并发标记和清除。
- G1 GC:分区算法,结合标记-压缩和复制算法。
- ZGC:分区算法,使用染色指针和读屏障技术,实现并发标记和压缩。
- Shenandoah GC:分区算法,使用并发标记和并发压缩技术。