本文是JVM第四讲:JVM性能调优
问题2:如果eden区比较大,会导致什么问题?
问题3:survivor区变小的影响点?
问题4:survivor区变大的影响点?
问题4:的影响点?
面试时如何回答
首先表态如果使用合理的JVM参数设置,在大多数情况下应该是不需要调优的;
其次说明可能还是存在少量场景需要调优,我们可以对一些JVM核心指标(GC次数,内存容量)配置监控告警,当出现波动时,人为介入分析评估;
最后举一个实际的调优例子来加以说明。见第三章
对于JVM的核心指标,我们的关注点和常用工具如下:
1)CPU指标
常见的命令:
// 显示系统各个进程的资源使用情况
top
// 查看某个进程中的线程占用情况
top -Hp pid
// 查看当前 Java 进程的线程堆栈信息
jstack pid
2)JVM 内存指标
常见的命令:
// 查看当前的 JVM 参数配置
ps -ef | grep java
// 查看 Java 进程的配置信息,包括系统属性和JVM命令行标志
jinfo pid
// 输出 Java 进程当前的 gc 情况
jstat -gc pid
// 输出 Java 堆详细信息
jmap -heap pid
// 显示堆中对象的统计信息
jmap -histo:live pid
// 生成 Java 堆存储快照dump文件
jmap -F -dump:format=b,file=dumpFile.phrof pid
3)JVM GC指标
JVM 的 GC指标一般是从 GC 日志里面查看,默认的 GC 日志可能比较少,我们可以添加以下参数,来丰富我们的GC日志输出,方便我们定位问题。
GC日志常用 JVM 参数:
// 打印GC的详细信息
-XX:+PrintGCDetails
// 打印GC的时间戳
-XX:+PrintGCDateStamps
// 在GC前后打印堆信息
-XX:+PrintHeapAtGC
// 打印Survivor区中各个年龄段的对象的分布信息
-XX:+PrintTenuringDistribution
// JVM启动时输出所有参数值,方便查看参数是否被覆盖
-XX:+PrintFlagsFinal
// 打印GC时应用程序的停止时间
-XX:+PrintGCApplicationStoppedTime
// 打印在GC期间处理引用对象的时间(仅在PrintGCDetails时启用)
-XX:+PrintReferenceGC
以上就是我们定位系统瓶颈的常用手段,大部分问题通过以上方式都能定位出问题原因,然后结合代码去找到问题根源。
定位出系统瓶颈后,在优化前先制定好优化的目标是什么,例如:
针对定位出的系统瓶颈制定相应的优化方案,常见的有:
Full GC (Metadata GC Threshold)
Metaspace used 35337K, capacity 56242K, committed 56320K, reserved 1099776K
{Heap before GC invocations=0 (full 0):
par new generation total 314560K, used 141123K [0x00000000c0000000, 0x00000000d5550000, 0x00000000d5550000)
eden space 279616K, 50% used [0x00000000c0000000, 0x00000000c89d0d00, 0x00000000d1110000)
from space 34944K, 0% used [0x00000000d1110000, 0x00000000d1110000, 0x00000000d3330000)
to space 34944K, 0% used [0x00000000d3330000, 0x00000000d3330000, 0x00000000d5550000)
concurrent mark-sweep generation total 699072K, used 0K [0x00000000d5550000, 0x0000000100000000, 0x0000000100000000)
Metaspace used 35337K, capacity 56242K, committed 56320K, reserved 1099776K
class space used 4734K, capacity 8172K, committed 8172K, reserved 1048576K
1.448: [Full GC (Metadata GC Threshold) 1.448: [CMS: 0K->10221K(699072K), 0.0487207 secs] 141123K->10221K(1013632K), [Metaspace: 35337K->35337K(1099776K)], 0.0488547 secs] [Times: user=0.09 sys=0.00, real=0.05 secs]
Heap after GC invocations=1 (full 1):
par new generation total 314560K, used 0K [0x00000000c0000000, 0x00000000d5550000, 0x00000000d5550000)
eden space 279616K, 0% used [0x00000000c0000000, 0x00000000c0000000, 0x00000000d1110000)
from space 34944K, 0% used [0x00000000d1110000, 0x00000000d1110000, 0x00000000d3330000)
to space 34944K, 0% used [0x00000000d3330000, 0x00000000d3330000, 0x00000000d5550000)
concurrent mark-sweep generation total 699072K, used 10221K [0x00000000d5550000, 0x0000000100000000, 0x0000000100000000)
Metaspace used 35337K, capacity 56242K, committed 56320K, reserved 1099776K
class space used 4734K, capacity 8172K, committed 8172K, reserved 1048576K
}
{Heap before GC invocations=1 (full 1):
par new generation total 314560K, used 0K [0x00000000c0000000, 0x00000000d5550000, 0x00000000d5550000)
eden space 279616K, 0% used [0x00000000c0000000, 0x00000000c0000000, 0x00000000d1110000)
from space 34944K, 0% used [0x00000000d1110000, 0x00000000d1110000, 0x00000000d3330000)
to space 34944K, 0% used [0x00000000d3330000, 0x00000000d3330000, 0x00000000d5550000)
concurrent mark-sweep generation total 699072K, used 10221K [0x00000000d5550000, 0x0000000100000000, 0x0000000100000000)
Metaspace used 35337K, capacity 56242K, committed 56320K, reserved 1099776K
class space used 4734K, capacity 8172K, committed 8172K, reserved 1048576K
1.497: [Full GC (Last ditch collection) 1.497: [CMS: 10221K->3565K(699072K), 0.0139783 secs] 10221K->3565K(1013632K), [Metaspace: 35337K->35337K(1099776K)], 0.0193983 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
Heap after GC invocations=2 (full 2):
par new generation total 314560K, used 0K [0x00000000c0000000, 0x00000000d5550000, 0x00000000d5550000)
eden space 279616K, 0% used [0x00000000c0000000, 0x00000000c0000000, 0x00000000d1110000)
from space 34944K, 0% used [0x00000000d1110000, 0x00000000d1110000, 0x00000000d3330000)
to space 34944K, 0% used [0x00000000d3330000, 0x00000000d3330000, 0x00000000d5550000)
concurrent mark-sweep generation total 699072K, used 3565K [0x00000000d5550000, 0x0000000100000000, 0x0000000100000000)
Metaspace used 17065K, capacity 22618K, committed 35840K, reserved 1079296K
class space used 1624K, capacity 2552K, committed 8172K, reserved 1048576K
}
元空间主要适用于存放类的相关信息,而存在内存碎片化说明很可能创建了较多的类加载器,同时使用率较低。
3、通过dump 堆存储文件发现存在大量 DelegatingClassLoader
分析结论:
如果上线了是WAR包的话可以在Tomcat设置
如果是Jar包直接 :java -jar 直接插入JVM命令就好了
JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具
Grafane:
#常用的设置
年轻代
#下面是一些不常用的
-xx:+Use xxx GC
xxx 代表垃圾收集器名称
原来是这样的:-Xmx6g -Xms6g -Xmn3g -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+ExplicitGCInvokesConcurrent -XX:+CMSScavengeBeforeRemark -XX:+PrintCommandLineFlags -XX:ErrorFile=/opt/zcy/modules/item-standard-center/hs_err_%p.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/zcy/modules/item-standard-center/ -Xloggc:/opt/zcy/modules/item-standard-center/gc.log -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCCause -XX:+PrintPromotionFailure
现在是这样的:-Xmx8g -Xms8g -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=45 -XX:MaxGCPauseMillis=200 -XX:G1MaxNewSizePercent=65 -XX:G1ReservePercent=5 -XX:InitiatingHeapOccupancyPercent=30 -XX:G1HeapRegionSize=16M -XX:+PrintAdaptiveSizePolicy -XX:+PrintCommandLineFlags -XX:ErrorFile=/opt/zcy/modules/log/hs_err_%p.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/zcy/modules/log/ -Xloggc:/opt/zcy/modules/log/gc.log -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCCause -XX:+PrintPromotionFailure -XX:+PrintTenuringDistribution -XX:+PrintHeapAtGC
堆内存是指由程序代码自由分配的内存,与栈内存作区分。
OLD GC 耗时较长影响业务
YGC耗时增加
YGC次数增加
仔细看GC日志,比对GC前和后,内存的变化