关于JVM调优,我理了一些工具和思路出来

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: JVM调优是争取高薪必须要掌握的一项技能,但是许多程序员在工作中很少遇到去JVM调优的情况,在这篇文章中,我整理了一些调优工具以及调优的思路,希望对大家有所帮助。

听说微信搜索《Java鱼仔》会变更强哦!


本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看哦


前言


JVM调优是争取高薪必须要掌握的一项技能,但是许多程序员在工作中很少遇到去JVM调优的情况,在这篇文章中,我整理了一些调优工具以及调优的思路,希望对大家有所帮助。


(一)调优工具


1.1 jmap


查看实例个数以及占用内存信息,最后一位表示进程id,可以用jps命令查看



jmap-histopid

网络异常,图片无法展示
|


num:代表序号 instances:代表实例数量 bytes:代表占用空间大小 classname:代表类的名称


查看堆的使用情况


jmap-heappid

通过该命令可以看到垃圾回收器,堆的参数以及堆的使用情况等信息。


网络异常,图片无法展示
|


堆内存dump


jmap-dump:format=b,file=D:/demo.hprofpid

通过命令将JVM运行文件拷贝出来,生成dump文件后,可以用JDK自带的可视化分析工具分析它,命令行下输入


jvisualvm

自动打开一个可视化窗口,将我们生成的文件装入:


网络异常,图片无法展示
|


所有信息都可以在可视化页面中看到


网络异常,图片无法展示
|


通过Jvm参数可设置内存溢出后自动导出Dump文件:


-XX:+PrintGCDetails-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=D:\jvm.dump

1.2 Jstack


通过Jstack命令加进程的id即可查找死锁,首先写一段代码制造一个死锁


publicclassDeadLockTest {
publicstaticObjectlock1=newObject();
publicstaticObjectlock2=newObject();
publicstaticvoidmain(String[] args) {
newThread(()->{
synchronized (lock1){
try {
System.out.println(Thread.currentThread().getName()+"begin");
Thread.sleep(1000);
                } catch (Exceptione) {
e.printStackTrace();
                }
synchronized (lock2){
System.out.println(Thread.currentThread().getName()+"end");
                }
            }
        }).start();
newThread(()->{
synchronized (lock2){
try {
System.out.println(Thread.currentThread().getName()+"begin");
Thread.sleep(1000);
                } catch (Exceptione) {
e.printStackTrace();
                }
synchronized (lock1){
System.out.println(Thread.currentThread().getName()+"end");
                }
            }
        }).start();
    }
}

这段代码会制造第一个线程锁住lock1等待锁lock2,第二个线程锁住lock2等待锁lock1的死锁。


首先通过jps命令查到进程号,我这里是15820,接着使用jstack命令:

jstack15820

通过该命令可以很轻松地找到死锁。


网络异常,图片无法展示
|


1.3 Jinfo


查看正在运行的Java项目参数 查看jvm的参数


jinfo-flagspid

可以查看到jvm的所有参数


网络异常,图片无法展示
|


查看Java系统参数


jinfo-syspropspid

可以查看到JDK版本、位置等信息。


1.4 jvisualvm


可视化的JVM监控工具,上面所讲到的这些命令,都可以直接在jvisualvm中看到可视化数据,但是这个工具在生产环境中需要谨慎使用,因为会占用一定资源。


(三)Jstat


jstat其实也是JVM自带的一个调优工具,但是我这里把他单独拿出来是因为正式对JVM调优中,这条命令是最常用的。


jstat命令可以查看堆内存各部分的使用量,以及加载类的数量等。


2.1 垃圾回收统计


评估内存使用及GC压力情况


jstat-gcpid

我执行这段代码后,出现了一串数据


网络异常,图片无法展示
|

所有参数的解释都放在下面了,结合垃圾回收一起看,就能懂了。


S0C:第一个Survivor大小(kb)S1C:第二个Survivor大小S0U:第一个Survivor区的使用大小S1U:第二个Survivor区的使用大小EC:eden区大小EU:eden区的使用大小OC:老年代大小OU:老年代使用大小MC:方法区大小(元空间)MU:方法区使用大小CCSC:压缩类空间大小CCSU:压缩类空间使用大小YGC:YoungGC次数YGCT:YoungGC时间(s)FGC:FullGC次数FGCT:FullGC时间(s)GCT:总的GC时间(s)

2.2 垃圾回收比例统计


给出各个区的使用比例:


jstat-gcutilpid

参数介绍:

S0:第一个Survivor区当前使用比例S1:第二个Survivor区当前使用比例E:eden区使用比例O:老年代使用比例M:元数据区使用比例CCS:压缩使用比例YGC:YoungGC次数FGC:FullGC次数FGCT:FullGC消耗时间GCT:垃圾回收消耗总时间

2.3 堆内存统计


统计堆内存的使用情况


jstat-gccapacitypid

介绍一下参数:

NGCMN:新生代最小容量NGCMX:新生代最大容量NGC:当前新生代容量S0C:第一个Survivor区大小S1C:第二个Survivor区的大小EC:eden区的大小OGCMN:老年代最小容量OGCMX:老年代最大容量OGC:当前老年代大小OC:当前老年代大小MCMN:最小元数据容量MCMX:最大元数据容量MC:当前元数据空间大小CCSMN:最小压缩类空间大小CCSMX:最大压缩类空间大小CCSC:当前压缩类空间大小YGC:YoungGC次数FGC:FullGC次数

2.4 新生代垃圾回收统计


统计新生代垃圾回收的数据


jstat-gcnewpid

介绍参数:

S0C:第一个Survivor区的大小S1C:第二个Survivor区的大小S0U:第一个Survivor区的使用大小S1U:第二个Survivor区的使用大小TT:对象在新生代存活的次数MTT:对象在新生代存活的最大次数DSS:期望的幸存区大小EC:eden区的大小EU:eden区的使用大小YGC:年轻代垃圾回收次数YGCT:年轻代垃圾回收消耗时间

2.5 新生代内存统计


统计新生代内存的使用情况


jstat-gcnewcapacitypid

2.6 老年代垃圾回收统计


统计老年代垃圾回收的数据


jstat-gcoldpid

参数介绍:

MC:方法区大小MU:方法区使用大小CCSC:压缩类空间大小CCSU:压缩类空间使用大小OC:老年代大小OU:老年代使用大小YGC:年轻代垃圾回收次数FGC:老年代垃圾回收次数FGCT:老年代垃圾回收消耗时间GCT:垃圾回收消耗总时间

2.7 老年代内存统计


统计老年代内存的使用情况


jstat-gcoldcapacitypid

参数介绍:

OGCMN:老年代最小容量OGCMX:老年代最大容量OGC:当前老年代大小OC:老年代大小YGC:年轻代垃圾回收次数FGC:老年代垃圾回收次数FGCT:老年代垃圾回收消耗时间GCT:垃圾回收消耗总时间

2.8 元空间统计


统计元数据空间的情况


jstat-gcmetacapacitypid

参数介绍

MCMN:最小元数据容量MCMX:最大元数据容量MC:当前元数据空间大小CCSMN:最小压缩类空间大小CCSMX:最大压缩类空间大小CCSC:当前压缩类空间大小YGC:年轻代垃圾回收次数FGC:老年代垃圾回收次数FGCT:老年代垃圾回收消耗时间GCT:垃圾回收消耗总时间

(三)JVM运行情况分析思路


上面的这些知识调优的工具,我们除了要了解这些工具的含义之外,还需要知道这些如何使用这些工具去分析JVM的运行情况。


3.1 分析年轻代对象增长速率


我们都知道新对象的产生会在eden区,因此我们可以通过下面的命令:


jstat-gcpid500010

每5秒执行一次,执行10次,然后观察这50秒内eden区增加的趋势,即可知道年轻代对象增长的速率。


3.2 分析YGC情况


jstat -gc命令中展示了YGCT和YGC,通过YGCT/YGC可以算出YGC的平均耗时。通过每隔一段时间输出一次我们也能观察出YGC的频率。


3.3 YGC后对象存活情况


每次YGC过后,eden区数量会大幅减少,而survivor和老年代的数量会增加,这样我们就能计算出每次每次YGC后存活的对象数量,以及推断老年代对象增长的速率。


3.4 分析FGC情况


分析FGC的思路和分析YGC一样,通过增长速率推断FGC频率,通过计算FGCT/FGC计算平均每次FGC耗时。


优化思路在于:尽量减少FGC的次数,避免频繁FGC对JVM性能的影响,因此尽量别让对象进入老年代,也就是每次YGC后存活的对象尽量少于Survivor的50%。


(四)GC日志


有时候系统突然运行缓慢无法找到原因时,我们可以把GC日志都打印出来,然后去分析gc日志中的关键性指标。


通过增加JVM参数的方式打印gc日志


-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-XX:+PrintGCDateStamps-Xloggc:./gc.log



GC日志中会把每一次GC的情况都打印出来,因此所有的GC都可以被分析到。


在GC日志中,有关GC日志的参数,我接下来也会专门写一篇来介绍,这样更加能让大家更加清楚一些。


我们还可以用一些工具比如GCeasy帮助我们去分析GC日志的情况。


(五)总结


整篇文章主要从工具出发,提供给大家GC调优的一个思路,但是GC调优又是一个很需要经验的事情。需要对垃圾回收器、Java内存分代等有很清晰的认知。对于当前工作环境中无法接触到调优的程序员们来说,需要做的就是把工具和思路牢牢掌握,等真正遇到的时候也不会一头雾水。我是鱼仔,我们下期再见!



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
13天前
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
21天前
|
Arthas Prometheus 监控
监控堆外使用JVM工具
监控堆外使用JVM工具
34 7
|
20天前
|
监控 Java 编译器
Java虚拟机调优指南####
本文深入探讨了Java虚拟机(JVM)调优的精髓,从内存管理、垃圾回收到性能监控等多个维度出发,为开发者提供了一系列实用的调优策略。通过优化配置与参数调整,旨在帮助读者提升Java应用的运行效率和稳定性,确保其在高并发、大数据量场景下依然能够保持高效运作。 ####
25 1
|
22天前
|
存储 算法 Java
JVM进阶调优系列(10)敢向stop the world喊卡的G1垃圾回收器 | 有必要讲透
本文详细介绍了G1垃圾回收器的背景、核心原理及其回收过程。G1,即Garbage First,旨在通过将堆内存划分为多个Region来实现低延时的垃圾回收,每个Region可以根据其垃圾回收的价值被优先回收。文章还探讨了G1的Young GC、Mixed GC以及Full GC的具体流程,并列出了G1回收器的核心参数配置,帮助读者更好地理解和优化G1的使用。
|
23天前
|
监控 Java 测试技术
Elasticsearch集群JVM调优垃圾回收器的选择
Elasticsearch集群JVM调优垃圾回收器的选择
39 1
|
1月前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
1月前
|
监控 Java 编译器
Java虚拟机调优实战指南####
本文深入探讨了Java虚拟机(JVM)的调优策略,旨在帮助开发者和系统管理员通过具体、实用的技巧提升Java应用的性能与稳定性。不同于传统摘要的概括性描述,本文摘要将直接列出五大核心调优要点,为读者提供快速预览: 1. **初始堆内存设置**:合理配置-Xms和-Xmx参数,避免频繁的内存分配与回收。 2. **垃圾收集器选择**:根据应用特性选择合适的GC策略,如G1 GC、ZGC等。 3. **线程优化**:调整线程栈大小及并发线程数,平衡资源利用率与响应速度。 4. **JIT编译器优化**:利用-XX:CompileThreshold等参数优化即时编译性能。 5. **监控与诊断工
|
1月前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
2月前
|
Arthas 监控 数据可视化
JVM进阶调优系列(7)JVM调优监控必备命令、工具集合|实用干货
本文介绍了JVM调优监控命令及其应用,包括JDK自带工具如jps、jinfo、jstat、jstack、jmap、jhat等,以及第三方工具如Arthas、GCeasy、MAT、GCViewer等。通过这些工具,可以有效监控和优化JVM性能,解决内存泄漏、线程死锁等问题,提高系统稳定性。文章还提供了详细的命令示例和应用场景,帮助读者更好地理解和使用这些工具。
|
2月前
|
监控 架构师 Java
JVM进阶调优系列(6)一文详解JVM参数与大厂实战调优模板推荐
本文详述了JVM参数的分类及使用方法,包括标准参数、非标准参数和不稳定参数的定义及其应用场景。特别介绍了JVM调优中的关键参数,如堆内存、垃圾回收器和GC日志等配置,并提供了大厂生产环境中常用的调优模板,帮助开发者优化Java应用程序的性能。