垃圾回收

1.对象被判定成垃圾的标准

没有被其他对象引用

2.判断对象是否为垃圾的算法

(1)引用计数法

 

优点and缺点

 

(2)可达性分析算法

 

根节点:类加载器、Thread、虚拟机栈的本地变量表、static 成员、常量引用、本地方法栈的变量

垃圾回收回收算法

1.标记-清除(Mark and Sweep)

 

缺点是内存空间碎片化太严重

2.复制算法(Copying)

(1)复制算法介绍

 

(2)复制算法优势

 

3.标记-整理算法(Compacting)

(1)标记整理算法介绍

 

(2)标记整理算法优点

 

4.分代收集算法

年轻代用的是复制算法
老年代 用的是标记清除或者标记整理算法

 

(2)年轻代内存空间

 

如果Eden区不能保存一个较大的对象,则会保存到老年代中,默认十五岁之后会转移到老年代中

 

 

  -XX:PretenureSizeThreshold 对象分配:对象优先在 Eden 区分配、大对象直接进入Old 区
-XX:MaxTenuringThreshold 长期存活对象进入 Old 区
-XX:+PrintTenuringDistribution如果希望跟踪每次新生代GC后,survivor区中对象的年龄分布,可在启动参数上增加。
-XX:TargetSurvivorRatio
设定survivor区的目标使用率。默认50,即survivor区对象目标使用率为50%。
为什么要动态的计算tenuring threshold的值呢?假设有很多年龄还未达到TenuringThreshold的对象依旧停留在survivor区,这样不利于新对象从eden晋升到survivor。因此设置survivor区的目标使用率,当使用率达到时重新调整TenuringThreshold值,让对象尽早的去old区。


(1)GC分类

 

从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC
Full GC 是清理整个堆空间—包括年轻代和老年代。

Major GC 是清理老年代

 JVM中的堆,一般分为三大部分:新生代、老年代、永久代:

永久代

    指内存的永久保存区域,主要存放Class和Meta(元数据)的信息,Class在被加载的时候被放入永久区域. 它和和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。

    在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。

 

(3)对象如何晋升到老年代

 

(4)设置参数

 

(5)触发full GC的方法

 

5.stop-theWorld

 

6.Safepoint

 

从线程角度看,safepoint可以理解成是在代码执行过程中的一些特殊位置,当线程执行到这些位置的时候,说明虚拟机当前的状态是安全的,如果有需要,可以在这个位置暂停,比如发生GC时,需要暂停暂停所以活动线程,但是线程在这个时刻,还没有执行到一个安全点,所以该线程应该继续执行,到达下一个安全点的时候暂停,等待GC结束。

JVM有两种运行模式Server与Client。两种模式的区别在于,Client模式启动速度较快,Server模式启动较慢;但是启动进入稳定期长期运行之后Server模式的程序运行速度比Client要快很多。这是因为Server模式启动的JVM采用的是重量级的虚拟机,对程序采用了更多的优化;而Client模式启动的JVM采用的是轻量级的虚拟机。所以Server启动慢,但稳定后速度比Client远远要快。

1. 当前是Client or Server?

使用Java -version命令就能显示出当前虚拟机处于哪种模式。 
Client: 
如下图所示,可以看到HotSpot虚拟机采用Client模式启动的。 
这里写图片描述

垃圾回收器分类

串行收集器
单线程收集器
Serial::Serial, Serial Old

并行收集器
吞吐量优先 是说垃圾收集线程之间并行工作 用户线程处在等待状态 适合交互性比较弱的场景
吞吐量:花在垃圾收集的时间和花在应用时间的占比 -XX:GCTimeRatio=<n>,垃圾收集时间占1/(1+n)
Parallel(吞吐量优先, Server 模式默认收集器):Parallel Scavenge, Parallel Old
并发收集器
并发收集器 停顿时间优先 垃圾收集线程和用户线程一起执行 适合对相应时间有要求的场景
停顿时间:垃圾收集器做垃圾回收中断应用执行的时间 -XX:MaxGCPauseMillis
Concurent(停顿时间优先):CMS , G1

如何选择垃圾收集器?

1. 优先调整堆的大小让服务器自己来选择

2. 如果内存小于100M,使用串行收集器

3。 如果是单核,并且没有停顿时间的要求,选择串行或者 JVM 自己选

4. 如果允许停顿时间超过1秒,选择并行或 JVM 自己选

5. 如果响应时间最重要,并且不能超过1秒,使用并发收集器




垃圾回收之新生代垃圾收集器

 


2.Serial收集器(复制算法-单线程-Client模式)

 

2.ParNew收集器(复制算法-多线程-Client模式)

 

3.Parallel Scavenge收集器(复制算法-多线程-Server模式下)

 

 

 

垃圾回收之老年代垃圾收集器

1.Serial Old收集器(标记整理算法-单线程-Client模式下)

 

2.Paraller Old收集器(标记整理算法-多线程-)

 

3.CMS收集器(标记清除算法)

 

4.G1收集器(新生代,老年代都可以用)

 

G1的几个概念

Region

SATB:Snapshot-At-The-Beginning,它是通过 Root Tracing 得到的,GC 开始时候存活对象的快照。

RSet:记录了其他 Region中的对象引用本 Region 中对象的关系,属于 points-into 结构

YoungGC

新对象进入 Eden 区

存活对象拷贝到Survivor 区

存活时间达到年龄阈值时,对象晋升到 Old 区

MixedGC

不是 FullGC,回收所有的 Young和所有的 Old

global concurrent marking

1. Initial marking phase: 标记 GC Root, STW

2. Root region scanning phase:标记存活 Region

3. Concurrent marking phase:标记存活的对象

4. Remark phase:重新标记,STW

5. Cleanup phase:部分 STW

MixedGC时机

InitiatingHeapOccupancyPercent

G1HeapWastePercent

G1MixedGCLiveThresholdPercent

G1MixedGCCountTarget

G1OldGCSetRegionThresholdPercent

-XX:+UseG1GC 开启 G1

-XX:G1HeapRegionSize=n, Region 的大小,1-32M,最多2048个

-XX:MaxGCPauseMillis=200 最大停顿时间

-XX:G1NewSizePercent、-XX:G1MaxNewSizePercent

-XX:G1ReservePercent=10 保留防止 to space溢出

-XX:ParallelGCThreads=n SWT线程数

-XX:ConcGCThreads=n 并发线程数=1/4*并行

最佳实践

年轻代大小:避免使用-Xmn, -XX:NewRatio 等显式 Young 区大小,会覆盖暂停时间目标

暂停时间目标:暂停时间不要太严苛,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响到吞吐量

需要切换到 G1的情况:

1. 50%以上的堆被存活对象占用

2. 对象分配和晋升的速度变化非常大

3. 垃圾回收时间特别长,超过了1秒

可视化 GC 日志分析工具

打印日志相关参数:

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution

例(默认为 ParallelGC, 其它的添加-XX:+UseConcMarkSweepGC或-XX:+UseG1GC即可):

JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log"

CMS日志格式
G1日志格式

在线工具:http://gceasy.io/

访问 GCeasy 官网导入日志即可获取可视化分析及优先建议

GCeasy 日志

GCViewer

mvn clean package -Dmaven.test.skip 生成 jar包,双击执行,导入日志即可进入图形化分析页面

GCViewer

原文地址:https://www.cnblogs.com/zyy1688/p/10830467.html