GC原理学习记录

253 阅读4分钟

什么是GC

追踪仍在使用的对象,对标记为垃圾的对象进行回收。

JVM体系结构

image.png

Java堆内存结构

+---------------------------+-------------------------------+-------------------+
|          |       |        |                               |                   |
|   Eden   |   S0  |   S1   |       Old generation          |      Perm         |
|          |       |        |                               |                   |
+---------------------------+-------------------------------+-------------------+
|<----Young Gen Space------>|

新生代

分为Eden、S0(Survivor)、S1(Survivor)三个区,通常以8:1:1比例分配
Eden用于存放new出来的对象等临时变量
S0,S1用于辅助回收内存
Eden中存活时间足够长会移到Survivor区,再长会分配到老年代
每次触发内存回收时,先将Eden和Survivor区中存活的对象移到另外一个Survivor区,之后对Eden和Survivor区执行回收操作

老年代

存放存活时间比较长的对象

永生代

存放Class类元数据和方法描述

GC回收机制

新生代

使用复制算法,即每次回收时将Eden和Survivor区中存活的对象移到另外一个Survivor区,之后对Eden和Survivor区执行回收操作,之后以此类推

老年代

使用引用计数和标记清除法

  • 引用计数

image.png

记录每个对象被引用的次数,回收掉没有被引用的链。

缺点就是不能处理循环引用

image.png

  • 标记清除法

image.png

标记所有可达的对象,清除不可达的对象

垃圾收集器

新生代:Serial收集器、ParNew收集器、Parallel Scavenge收集器
老年代:Serial Old收集器、Parallel Old收集器、CMS收集器。

Serial收集器

单线程回收
新生代采用复制算法,老年代采用标记压缩算法。应用实践:

java -xx:+UseSerialGC com.mypackages.MyExecutableClass

Parallel收集器

并行收集器,在GC期间,所有CPU都在并行清理垃圾
新生代采用复制算法,老年代采用标记清除整理算法,不适合低延迟系统。应用实践:

java -xx:+UseParallelGC com.mypackages.MyExecutableClass

CMS收集器

标记清除垃圾收集器。
使用空闲列表管理内存回收,不对老年代进行整理。在标记清除阶段和应用线程并处理。
新生代采用标记-复制算法,老年代采用标记-清楚算法。
适用于多核CPU,降低延迟,缺点是有可能会和应用线程抢资源。
CMS关键阶段:

  • 初始标记 标记老年代中GC root或者新生代能够直接链接到的对象。

image.png

  • 并发标记 标记老年代中前一阶段找到的节点仍然存活的节点。

image.png

  • 重新标记-并发预清理 修正并法标记时新生成的变动记录,统计脏对象和从脏对象可达的对象节点。

image.png

  • 并发清除 与应用线程并发执行,清理回收未使用的对象。

image.png

应用示例

java -xx:+UseConcMarkSweepGC com.mypackages.MyExecutableClass

JVM参数设置

参数名说明
-Xms 与 -Xmx-Xms用于指定Java应用使用的最小堆内存,如-Xms1024m;
-Xmx用于指定Java应用使用的最大堆内存。
-Xmn设置堆内存中新生代的容量,从而间接控制老年代的容量,如-Xms1024m -Xmx1024m -Xmn200m,那么老年代的容量则为8024M
-XX:PermSize 与 -XX:MaxPermSize设置永生代的初始容量和最大容量
-XX:SurvivorRatio设置新生代总Eden和Survivor区的容量比,默认为8,即8(Eden):1(S0):1(S1)
-XX:+UseSerialGC虚拟机运行在client模式下默认值,使用Serial+Serial Old收集器进行回收,+代表使用,-代表禁用
-XX:+UseParNewGC使用ParNew+Serial Old收集器进行回收
-XX:+UseConcMarkSweepGC使用ParNew+CMS+Serial Old收集器进行回收,Serial Old用于CMS回收错误时使用
-XX:+UseParallelGC虚拟机运行在Server模式下默认值,使用Parallel Scavenge + Serial Old(PS MarkSweep)进行回收
-XX:+UseParallelOldGC使用Parallel Scavenge + Serial Old进行回收
-XX:PretenureSizeThreshold设置直接分配到老年代的对象大小,单位为字节,如-XX:PretenureSizeThreshold=3145728,标示对象超过3M直接在老年代分配
-XX:MaxTenuringThreshold设置对象坚持到老年代的年龄,默认15,即对象坚持过15次GC则放入老年代
-XX:ParellelGCThreads设置对象GC时线程数,只对并行GC机制有效
-XX:CMSInitiatingOccupancyFraction设置CMS收集器在老年代空间被占用多少百分比后才触发GC,默认68
-XX:+UseCMSCompactAtFullCollection设置CMS收集器执行GC后是否进行一次内存碎片整理,仅老年代收集器设置为CMS才有效
-XX:CMSFullGCsBeforeCompaction设置CMS收集器在执行多少次GC后才执行一次内存碎片整理,默认2
-XX:+PrintGCDetails输出GC详细情况
-XX:+PrintGCDateStamps指定输出GC时间格式
-Xloggc指定GC日志输出位置