垃圾回收

发布时间 2023-07-24 17:37:10作者: pr1s0n

如何判断对象可以回收

可达性分析算法

根对象:肯定不能被回收的对象

  • Java虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象
  • 扫描堆中的对象,看是否能够沿着GC ROOT为起点的引用链找到该对象,找不到则代表可以回收

哪些对象可以作为GC ROOT

  • 在虚拟机栈(栈帧中的本地变量表)中引用的对象,比如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等
  • 在方法区中类静态属性引用的变量、比如Java类的引用类型静态变量
  • 在方法区中常量引用的对象,比如String Table中的引用
  • 在本地方法栈中JNI(即通常说哦Native方法)引用的对象
  • Java虚拟机内部的引用,如基本数据类型对应的CLass对象,一些常驻的异常对象(如空指针异常、缓冲区溢出)等,还有系统类加载器
  • 所有被同步锁(synchronized关键字)持有的对象
  • 反应Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等

五种引用

  • 软引用
  • 强引用
  • 弱引用
  • 虚引用
  • 终结器引用
image-20221024155921430

实线:强引用 虚线:软弱虚终结器引用

image-20221024160317951

虚引用

虚引用对象在被回收时,虚引用自己会被放入引用队列,因为ByteBuffer可以被回收,但是它创建的直接内存不是Java虚拟机中的内存,所以无法直接被回收。

当虚引用对象放入引用队列后,间接调用虚引用Cleanner直接内存地址,使用Unsafe.freeMemory方法释放直接内存占用。

终结器引用

当没有强引用引用A4对象时,终结器引用加入引用队列,引用队列中有一个优先级很低的finallizeHandle线程,在某个时机轮到它运行之后调用未被回收的对象,再下一次垃圾回收时将其回收,因此这种方法垃圾回收效率并不高。

image-20221024162003324

垃圾回收算法

标记清除(Mark Sweep)

image-20221024172457765

优点:速度快

缺点:不连续,内存碎片多

标记整理(Mark Compact)

image-20221024172724084

优点:没有内存碎片

缺点:效率较低

复制(Copy)

大小相等两块内存区域

从from复制到to

image-20221024172949763

交换位置

image-20221024173053980

优点:不会有内存碎片

缺点:需要占用双倍内存空间

分代垃圾回收

image-20221024174219550
  • 对象首先分配在伊甸园区
  • 新生代空间不足时,出发Minor GC,伊甸园和From存活的对象使用复制算法复制到To中,存活的对象年龄+1,交换From和To
  • Minor GC 会引发stop the world,暂停其他用户的线程,等垃圾回收结束用户线程才恢复运行
  • 当对象寿命超过阈值时,会晋升至老年代,最大寿命是15次(4bit)
  • 当老年代空间不足,会先尝试触发Minor GC ,如果之后空间仍不足,那么出发Full GC,StopTheWorld的时间更长

当出现大对象,即伊甸园区放不下的时候,会不判定年龄直接放入老年代

一个线程内的内存溢出不会导致主线程结束

相关VM参数

含义 参数
堆初始大小 -Xms
堆最大大小 -Xmx或-XX:MaxHeapSize=size
新生代大小 -Xmn或(-XX:NewSize=size + -XX:MaxNewSize=size)
幸存区比例(动态) -XX:InitialSurvivorRatio=ratio和-XX:+UseAdaptivePolicy
晋升阈值 -XX:MaxTenuringThreshold=threshold
晋升详情 -XX:+PrintTenuringDistribution
GC详情 -XX:+PrintGCDetails -verbose:gc
FullGC和Minor GC -XX:+ScavengeBeforeFullGC

垃圾回收器

串行

  • 单线程
  • 堆内存较小

吞吐量优先

  • 多线程
  • 堆内存较大,多核CPU
  • 让单位时间内STW时间最短

响应时间优先

  • 多线程
  • 堆内存较大,多核CPU
  • 尽可能让单次STW时间最短
image-20221025103439994

G1

image-20221025104825358

参数:

  • -XX:+UseG1GC
  • -XX:G1HeapRegionSize=size
  • -XX:MaxGCPauseMillis=time
Young Collection
image-20221025105505941 image-20221025105521804
Young Collection + VM(并发标记)
  • 在Young GC时会进行GC Root的初始标记
  • 老年代占用堆空间的比例达到阈值时,进行并发标记(STW),由-XX:InitatingHeapOccupancyPercent=percent(默认45%)
image-20221025105746114
Mixed Collection
image-20221025105839855
Full GC
  • SerialGC
    • 新生代内存不足发生的垃圾收集:Minor gc
    • 老年代内存不足发生的垃圾收集:full gc
  • ParallelGC
    • 新生代内存不足发生的垃圾收集:Minor gc
    • 老年代内存不足发生的垃圾收集:full gc
  • CMS
    • 新生代内存不足发生的垃圾收集:Minor gc
    • 老年代内存不足
  • G1
    • 新生代内存不足发生的垃圾收集:Minor gc
    • 老年代内存不足
Young Collection跨代引用
image-20221025111027224