目录
一、垃圾回收机制:
1、垃圾回收的过程:
JVM内存的程序计数器、虚拟机栈、本地方法栈的生命周期是和线程是同步的,随着线程的销毁而自动释放内存,所以只有方法区和堆需要GC,方法区主要是针对常量池的回收和对类型的卸载,堆针对的是不再使用的对象进行回收内存空间。我们常说的GC一般指的是堆的垃圾回收,堆内存可以进一步划分新生代和老年代,老年代会发生Full GC,年轻代会发生Minor GC,年轻代又可以分成三部分:一个Eden区和两个Survivor区(即From区(S0)和To区(S1)),比例为8:1:1。
Minor GC主要针对Java堆中的新生代(Young Generation)进行垃圾回收。
- 当程序创建新的对象时,这些对象首先会被分配到Eden区。当Eden区满时,会触发Minor GC。在Minor GC过程中,垃圾回收器会扫描并标记所有存活的对象,然后将这些存活的对象移动到Survivor区。
Full GC主要针对Java堆中的老年代(Old Generation)进行垃圾回收。老年代中存放的是存活时间较长的对象。
- Full GC会对整个Java堆进行垃圾回收,包括新生代和老年代。Full GC的触发条件通常有多种,例如老年代空间不足、永久代空间不足、频繁的Minor GC等。
在GC开始时,对象会存在Eden和From区,To区是空的,当Eden区没有足够的内存分配给对象时,虚拟机会发起一次Minor GC。进行GC时,Eden区存活的对象会被复制到To区,From区存活的对象会根据年龄值决定去向,达到阈值的对象会被移动到老年代中,没有达到阈值的对象会被复制到To区(但如果符合“动态年龄判断”的条件,即使未达到阈值也会从Survivor区直接移动到老年代)。这时Eden区和From区已经被清空了,接下来From区和To区交换角色,以保证To区在GC开始时是空的。Minor GC会一直重复这样的过程,直到To区被填满,To被填满后,会将所有对象移动到老年代中。如果老年代内存空间不足,则会触发一次Full GC。
GC年龄阈值默认是15,该阈值是否可以调整?能否调整为16?年龄阈值是可以调整的,但是由于对象头中只分配了 4bit 位用于记录对象的GC年龄,因此最大只能调整为15
2、确认对象是否存活:
垃圾收集器在对堆进行回收前,首先要确定对象是否存活,判断对象是否存活主要有两种算法:引用计数算法 和 可达性分析算法。
(1)引用计数算法:对象创建时,给对象添加一个引用计数器,每当有一个地方引用到它时,计数器值加1;引用失效时,计数器值减1;当计数值值为0时,这个对象就是不可能再被引用的。
(2)可达性分析算法:以“GC Roots”对象为起点,从这些节点向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连接时,则证明此对象是不可用的。
GC Roots对象包括:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象;
- 本地方法栈中JVM(Native)引用的对象;
- 方法区中类静态属性引用的对象;
- 方法区中常量引用的对象。
四种对象引用类别:(关联强度向下递减)
- 强引用:GC不会回收强引用的对象。
- 软引用:如果内存不紧张,这类对象可以不回收;如果内存紧张,这类对象就会被回收
- 弱引用:被弱引用关联的对象,只能生存到下一次垃圾收集。
- 虚引用:目的是能在对象被回收时收到一个系统通知。
💡注:在java中当我们创建一个对象时Object obj=new Object(),默认的引用就是强引用,如需更换则可以通过java提供的对应的方法转换。
💡(3)三色标记算法(CMS、G1):
三色标记法是一种垃圾回收法,它可以让JVM不发生或仅短时间发生STW(Stop The World),从而达到清除JVM内存垃圾的目的。JVM中的CMS、G1垃圾回收器的并发标记算法所使用垃圾回收算法即为三色标记法。
三色标记算法思想
三色标记法将对象的颜色分为了黑、灰、白,三种颜色。
白色:该对象没有被标记过。(对象垃圾)
灰色:该对象已经被标记过了,但该对象下的属性没有全被标记完。(GC需要从此对象中去寻找垃圾)
黑色:该对象已经被标记过了,且该对象下的属性也全部都被标记过了。(程序所需要的对象)
算法流程
从我们main方法的根对象(JVM中称为GC Root)开始沿着他们的对象向下查找,用黑灰白的规则,标记出所有跟GC Root相连接的对象,扫描一遍结束后,一般需要进行一次短暂的STW(Stop The World),再次进行扫描,此时因为黑色对象的属性都也已经被标记过了,所以只需找出灰色对象并顺着继续往下标记(且因为大部分的标记工作已经在第一次并发的时候发生了,所以灰色对象数量会很少,标记时间也会短很多), 此时程序继续执行,GC线程扫描所有的内存,找出扫描之后依旧被标记为白色的对象(垃圾),清除。