JVM基础知识整理(四)性能监控与内存调优
学习JVM最终的学以致用就在于做好性能监控和内存调优。在平时开发过程中,当开发完一段代码段(如接口方法、并发方法)后,特别是涉及到多线程、高频业务调用的,我们就需要预估实际的并发量,做好必要充分的压力测试,在测试过程中,这时善于利用好JDK提供的性能监控工具和熟知内存调优方法就显得相当重要,从而避免生产系统上因自身代码引起的意外事故(如果在生产系统上服务使用的是单机部署,并发生OOM、访问隔断时间变得缓慢需要重启的情况的话,其结果自然对客户业务造成恶劣影响,像在银行项目中,组织就会被投诉,个人或者领导都会受处分,对于开发人员的成长来说,压力测试、性能调优必须得到重视)。
性能监控工具
这里先介绍jdk自带的jvm性能监控非常实用的工具。
1)jstat-JVM实时监视工具
常用命令示例:jstat -gcutil [进程id] [查询间隔],作用:按时间间隔(毫秒为单位)实时查询对应进程号的JVM中堆的各使用空间情况。该命令行工具特别适用于在生产环境上的命令行控制台中实时监控内存情况,操作方便。执行样例如下:
各参数含义:S0-survivor0区占用空间百分比,S1-survivor1区占用空间百分比,E-Eden区占用空间百分比,O-老年代占用空间百分比,M-metaspace占用空间百分比,CCS-压缩率相关可忽略,YGC-年轻代GC次数,YGCT-年轻代GC总耗时N秒,FGC-老年代GC次数,FGCT-老年代GC总耗时N秒,GCT-所有GC总耗时N秒。如图为一OOM程序GC过程的示例,从图中可从GCT、YGCT开始看起,发现年轻代GC已逐渐耗时没有变化,说明那个时刻已OOM。
2)jinfo-JVM配置信息查询工具
常用命令示例:jinfo -flags [进程id],作用:实时查看JVM配置参数信息。执行样例如下:
3)jstack-Java方法堆栈跟踪工具
当需要在生产上排查某一时刻应用开始cpu占用较高、长时间需要等待等问题时,jstack命令有助于帮我们跟踪是运行到哪行代码出现问题。首先使用 top -p <pid> 命令可以查看java进程的总体CPU和内存占比:
然后用top -Hp <pid>命令可以查看该进程下各线程的CPU和内存占比:
然后用printf "%x
" <tid> 将线程号转成16进制:
此时使用 jstack -l <pid> > ./jstack-log.txt 来获取线程快照结果并输入到指定文件,打开txt文件,根据线程号进行搜索,一般可以找到当前正在运行的代码行,此时即可分析代码:
4)jvisualVM-可视化多合一故障处理工具
jvisualVM功能强大,同时具有GC日志分析、内存变化监视的功能,在日常开发中可使用该工具测试高并发内存调优非常方便。使用教程如下:
在jdk的bin目录下可找到该exe,双击打开:
左边的导航栏会自动显示本地当前可以监视到的JVM进程,点击后可查看到JVM参数、堆内存变化实时情况:
如需监视应用服务器内存变化情况,则应用服务器的需先配置好参数,如在setenv.sh中配置参数,则参考的配置项如下:
JAVA_OPTS="-Djava.rmi.server.hostname=192.168.0.216 -Dcom.sun.management.jmxremote.port=1100 -Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false",分别表示服务器IP、自定义的端口、关闭ssl、关闭登录认证。
然后在主界面上点击远程-添加远程主机-添加JMX连接,IP和端口号与服务器配置保持一致:
点击确定后,即可实时监控服务器内存变化。此外,jvisualVM还有分析GC日志的功能,可对dump日志文件进行分析,如下:
内存调优参数
内存调优参数较多,以下分几个部分介绍:
1)堆栈配置相关
-Xms3550m:设置初始堆大小为3550m。默认物理内存的1/64(<1GB)。实际上一般建议该值需调大,保持与最大堆内存一致。
-Xmx3550m:设置最大堆大小为3550m。默认物理内存的1/4(<1GB) 。到生产上看情况可以设置到物理内存50%到80%,将最大堆与初始化调为一致,可以避免JVM在运行过程中不断调整堆大小、减少发生GC的次数。
-Xmn1024m:设置年轻代大小为1024m。增大年轻代后,将会减小年老代大小,此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8,即大约1/3,剩余空间即为老年代的空间。该参数设置后等同于设置了 XX:NewSize 、-XX:MaxNewSize,故后两个参数一般不做设置。
-XX:PermSize=512m:设置永久代初始大小为512m。对JDK1.8无效,默认为物理内存的1/64。
-XX:MaxPermSize=512m: 设置永久代最大值 为512m。对JDK1.8无效,默认为物理内存的1/4,对于较多class、jar文件的war包,如不设置初始值容易OOM。如设置了该值,PermSize可不必设置。按Sun官方推荐 MaxPermSize设置为老年代存活对象的1.2-1.5倍。
-Xss128k: 每个线程的堆栈大小为128k。一般不需要调,正常是足够的。
-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与老年代的比值。 Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。
-XX:SurvivorRatio=4: 设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6,按默认设置为8即可。
-XX:MaxTenuringThreshold=0: 设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。 对于年老代比较多的应用,可以提高效率. 该配置应用较少。
2)辅助信息相关
-XX:+PrintGC:输出GC日志。
-XX:+PrintGCDetails:输出GC的详细日志。
-XX:+PrintGCTimeStamps:输出GC日志文件中的时间戳形式为以基准时间。
-XX:+PrintGCDateStamps:输出GC日志文件中的时间戳形式为以日期的形式,如 2013-05-04T21:53:59.234+0800。
-Xloggc:/GClogs/gc.log:日志文件的输出路径。目录需先创建,经以上配置项,GC日志示例如下,日志中可以清楚看到堆内新生代、老年代内存变化情况:
-XX:+PrintHeapAtGC:在进行GC的前后打印出堆的信息,使用较少。
-XX:+HeapDumpOnOutOfMemoryError: 生成内存溢出的dump日志文件。一般该日志文件有助于分析OOM,所以常加此配置项。
-XX:HeapDumpPath=/GClogs/:dump日志文件路径。目录需先创建。
3)eclipse调优参数推荐
eclipse启动时的速度可以通过修改其JVM参数来优化,修改 ${ECLIPSE_HOME}/eclipse.ini 文件即可,推荐配置如下:
-Xverify:none
-Xms512m
-Xmx512m
-Xmn128m
-XX:PermSize=96m
-XX:MaxPermSize=96m
-XX:+DisableExplicitGC
-Xnoclassgc
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=85
日常开发中,对JDK的参数设置一般设置Xms、Xmx、MaxPermSize(jdk1.7)即可,各值应低于生产配置项。
以上是 JVM基础知识整理(四)性能监控与内存调优 的全部内容, 来源链接: utcz.com/z/518743.html