什么是GC
追踪仍在使用的对象,对标记为垃圾的对象进行回收。
JVM体系结构
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区执行回收操作,之后以此类推
老年代
使用引用计数和标记清除法
- 引用计数
记录每个对象被引用的次数,回收掉没有被引用的链。
缺点就是不能处理循环引用
- 标记清除法
标记所有可达的对象,清除不可达的对象
垃圾收集器
新生代: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或者新生代能够直接链接到的对象。
- 并发标记 标记老年代中前一阶段找到的节点仍然存活的节点。
- 重新标记-并发预清理 修正并法标记时新生成的变动记录,统计脏对象和从脏对象可达的对象节点。
- 并发清除 与应用线程并发执行,清理回收未使用的对象。
应用示例
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日志输出位置 |