JVM GC优化

查看JVM的GC过程

在启动你的程序的时候,使用-verbose:gc 参数,将程序的 GC情况输出至 log 文本文件中。对log 文件进行简要分析。
输入的参数为“-verbose:gc -Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails”将日志文件输入到gc.log中并且打印时间戳和GC的详细信息。
JVM GC优化_第1张图片
输出的gc.log文件为:
JVM GC优化_第2张图片
发现:Minor GC的频率较高,Full GC的频率较低。
Minor GC每次耗费的时间0.01-0.03秒之间,Full GC的每次耗费的时间约为0.13秒。
每次GC前后 heap 中各区域占用情况的变化:
每次Minor GC前后,PSYoungGen区域的占用减少。
每次Full GC前后,ParOldGen区域的占用增加。

用jstat命令行工具的-gc和-gcutil参数

打开cmd,找到jdk的目录下的bin文件夹,在其中执行jstat –gc 22784 250 112每250毫秒查询一次进程22784垃圾收集状况,一共查询112次。其中的22784为pid。
JVM GC优化_第3张图片
其中:S0C:年轻代中第一个存活区的大小
S1C:年轻代中第二个存活区的大小
S0U:年轻代中第一个存活区已使用的空间 (KB)
S1U:年轻代中第二个存活区已使用的空间 (KB)
EC: Edem区大小
EU: 年轻代中Edem区已使用的空间 (KB)
OC: 老年代大小
OU: 老年代已使用的空间 (KB)
PC: 持久代大小
PU: 持久代已使用的空间 (KB)
YGC: 从应用程序启动到采样时young gc的次数
YGCT: 从应用程序启动到采样时young gc的所用的时间(s)
FGC: 从应用程序启动到采样时full gc的次数
FGCT: 从应用程序启动到采样时full gc的所用的时间
GCT: 从应用程序启动到采样时整个gc所用的时间
然后再使用-gcutil (GC统计汇总),输入命令jstat –gcutil 25228 250 112.
JVM GC优化_第4张图片
其中:S0 — Heap上的 Survivor space 0 区已使用空间的百分比
S1 — Heap上的 Survivor space 1 区已使用空间的百分比
E — Heap上的 Eden space 区已使用空间的百分比
O — Heap上的 Old space 区已使用空间的百分比
P — Perm space 区已使用空间的百分比
YGC — 从应用程序启动到采样时发生 Young GC 的次数
YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC — 从应用程序启动到采样时发生 Full GC 的次数
FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
分析:
程序运行期间young gc的次数大约为38次,young gc的总时间时间大约为0.816s,平均每次young gc的时间为0.0215秒,时间较短,属于正常。full gc的次数为1次,用时0.151秒,整个程序用于垃圾回收的总时间为1.12s,程序总运行时间为27.552s,大约占其时间的4.07%。
4次young gc之后,垃圾内存被从Eden space区(E)放入了Old space区(O),并引起了百分比的变化,导致Survivor space使用的百分比从31.25%(S0)降到25.00%(S1)。有效释放了内存空间。上图中,我们可以看到,一次full gc之后,Old space区(O)的内存被回收,从90.31%降到52.31%。
常驻内存区(P)的使用率,始终停留在93%-95%左右,说明常驻内存没有突变,比较正常。
young gc和full gc能够正常发生,而且都能有效回收内存,常驻内存区变化不明显,则说明java内存释放情况正常,垃圾回收及时,java内存泄露的几率就会大大降低。

使用jmap -heap命令行工具

在命令行中输入jmap –heap 10864,显示如图:
JVM GC优化_第5张图片
虚拟机当前使用的gc策略为Parallel GC,heap 的配置情况(各区域的大小等)为OldSize为85.5MB,MaxHeapSize为2018.0MB,NewSize为42.5MB,MaxNewSize为672.5MB,MetaspaceSize为20.8MB,MaxMetaspaceSize为17592186044415MB。heap 的使用情况统计,Eden已用101MB,剩余79MB,FromSpace已用31MB,剩余11MB,ToSpace已用0MB,剩余44MB。Old已用86.5MB,剩余56.7MB。

使用jmap -histo命令行工具

在命令行中输入jmap –histo 17080,产生的结果如图:
JVM GC优化_第6张图片
查询当前装载进内存的各类的实例数目为2767273,及内存占用情况为165538304bytes,约为157MB。

使用jmap -permstat命令行工具

在命令行中输入jmap –clstats 848(在jdk8之前用jmap -permstat命令)
JVM GC优化_第7张图片
class loader总数为76,class总数为1687,总字节为3020254,alive的为1,dead为75。

配置JVM参数并发现最优参数配置

JVM中的堆

首先我们要了解JVM中堆的分区情况:
JVM GC优化_第8张图片
JVM堆分为新生代,旧生代和年老代,新生代可用的gc方式有:串行gc(Serial Copying),并行回收gc(Parellel Scavenge),并行gc(ParNew),旧生代和年老代可用的gc方式有串行gc(Serial MSC),并行gc(Parallel MSC),并发gc(CMS)。

GC优化的标准

Minor GC执行时间不到50ms;
Minor GC执行不频繁,约10秒一次;
Full GC执行时间不到1s;
Full GC执行频率不算频繁,不低于10分钟1次;

重要的参数的含义

-Xmn 设置新生代大小
-XX:NewRatio 新生代(eden+2*s)和老年代(不包含永久区)的比值,例如:4,表示新生代:老年代=1:4,即新生代占整个堆的1/5
-XX:SurvivorRatio(幸存代) 设置两个Survivor区和eden的比值。例如:8,表示两个Survivor:eden=2:8,即一个Survivor占年轻代的1/10
-Xmx –Xms:指定最大堆和最小堆
-XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=15 指定rmi调用时gc的时间间隔

优化方式

较大的heap会导致较少发生GC,但每次GC时间很长 。较小的heap,则需要频繁GC,但每次GC的时间较短。
heap尺寸可随时间变化 ,heap尺寸变化时需要full GC 。
CMS是用于对tenured generation的回收,也就是年老代的回收,目标是尽量减少应用的暂停时间,减少full gc发生的几率,利用和应用程序线程并发的垃圾回收线程来标记清除年老代。在我们的应用中,因为有缓存的存在,并且对于响应时间也有比较高的要求,因此希望能尝试使用CMS来替代默认的server型JVM使用的并行收集器,以便获得更短的垃圾回收的暂停时间,提高程序的响应性。
例如,程序每秒都有大约400M的海量短命对象产生,那么我们可以采用CMS收集器,并且对MaxTenuringThreshold(生代对象撑过过多少次minor gc才进入年老代的设置)设置为较高参数(默认为0)。得到了很大的性能优化。

Shallow heap & Retained heap

Shallow Size
对象自身占用的内存大小,不包括它引用的对象。
针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。
针对数组类型的对象,它的大小是数组元素对象的大小总和。
Retained Size
Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C, C就是间接引用)
换句话说,Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。
不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。

参考GC优化文献

gc优化小记
https://blog.csdn.net/u013593306/article/details/51838350
JVM GC 机制与性能优化
https://blog.csdn.net/antony9118/article/details/51375662
频繁GC (Allocation Failure)及young gc时间过长分析
https://my.oschina.net/go4it/blog/1628795
《JVM故障诊断指南》之6 —— JVM verbose GC 输出日志指南
https://blog.csdn.net/wang8118/article/details/46273385
在IDE的后台打印GC日志
https://blog.csdn.net/u011767040/article/details/49180973
JVM调优:选择合适的GC collector
https://blog.csdn.net/macyang/article/details/8731313
java jvm内存管理/gc策略/参数设置
https://www.cnblogs.com/yang-hao/p/5939487.html
java 堆中新生代老年代
https://blog.csdn.net/lvyuan30276/article/details/48527123

你可能感兴趣的:(jvm,gc)