解析JVM之垃圾收集篇,超详细!
点击蓝色“程序员的时光 ”关注我 ,标注“星标”,及时阅读最新技术文章!
小伙伴儿们,大家好!上一次我们了解了JVM基础知识——全面解析JVM,超详细!
今天来学习JVM垃圾回收相关内容,作为面试必问的知识点,来深入了解一波!
1,判断对象是否死亡
1.1,引用计数算法
public class ReferenceCountingGc {
public Object instance = null;
public static final int _1MB = 1024*1024;
public static void main(String[] args) {
ReferenceCountingGc objA = new ReferenceCountingGc();
ReferenceCountingGc objB = new ReferenceCountingGc();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
}
}
1.2,可达性分析算法
虚拟机栈(栈帧中的本地变量表)中引用的对象 方法区中类静态属性引用的对象 方法区中常量引用的对象 本地方法栈(Native 方法)中引用的对象
2,再谈引用
reference
类型的数据存储的数值代表的是另一块内存的起始地址,就称这块内存代表一个引用。JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用、虚引用四种(引用强度逐渐减弱)。2.1,强引用
OutOfMemoryError
错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。2.2,软引用
ReferenceQueue
)联合使用,如果软引用所引用的对象被垃圾回收,JAVA 虚拟机就会把这个软引用加入到与之关联的引用队列中。2.3,弱引用
ReferenceQueue
)联合使用,如果弱引用所引用的对象被垃圾回收,Java 虚拟机就会把这个弱引用加入到与之关联的引用队列中。2.4,虚引用
OutOfMemory
)等问题的产生。3,废弃常量以及无用类
3.1,如何判断一个常量是废弃常量?
abc
" ,如果当前没有任何String
对象引用该字符串常量的话,就说明常量"abc
"就是废弃常量,如果这时发生内存回收的话而且有必要的话," abc
"就会被系统清理出常量池。3.2,如何判断一个类是无用的类?
该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。 加载该类的 ClassLoader
已经被回收。该类对应的 java.lang.Class
对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
4,垃圾收集算法
4.1,标记--清除算法
效率问题:标记和清除两个过程的效率都不高; 空间问题:标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
4.2,复制算法
4.3,标记--整理算法
4.4,分代收集算法
5,垃圾收集器
5.1,Serial
收集器
Serial
收集器是最基本、历史最悠久的垃圾收集器了。从名字上看是串行的意思,这个收集器是一个单线程的新生代收集器。它的 “单线程” 的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。5.2,ParNew
收集器
并行(Parallel) :指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。 并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行,可能会交替执行),用户程序在继续运行,而垃圾收集器运行在另一个 CPU 上。
5.3,Parallel Scavenge
收集器
java -XX:+PrintCommandLineFlags -version
命令查看-XX:InitialHeapSize=197918400 -XX:MaxHeapSize=3166694400 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
Parallel Scavenge + Parallel Old
,如果指定了-XX:+UseParallelGC
参数,则默认指定了-XX:+UseParallelOld GC
,可以使用-XX:-UseParallelOldGC
来禁用该功能。5.4,Serial Old
收集器
5.5,Parallel Old
收集器
5.6,CMS
收集器
初始标记: 暂停所有的其他线程,并记录下直接与 root 相连的对象,速度很快 ; 并发标记: 同时开启 GC 和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程可能会不断的更新引用域,所以 GC 线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方。 重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短 并发清除: 开启用户线程,同时 GC 线程开始对未标记的区域做清扫。
对 CPU 资源敏感; 无法处理浮动垃圾; 它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生。
5.7,G1
收集器
并行与并发:G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 java 程序继续执行。 分代收集:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。 空间整合:与 CMS 的“标记--清理”算法不同,G1 从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。 可预测的停顿:这是 G1 相对于 CMS 的另一个大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内。
《深入理解Java虚拟机(第2版).周志明》
https://xiaozhuanlan.com/topic/1847690325#section1java
评论