网站首页 > 技术文章 正文
一、背景
接着上一篇的知识:性能测试能力提升-JVM GC原理,本篇文章,我们将主要介绍JVM GC监控和优化相关的知识:
- 命令行方式监控GC
- 图形化方式监控GC
- 什么时候需要开始GC优化?
- GC优化的目的
- GC优化的步骤
- 常用JVM参数配置实例
二、JVM GC监控
2.1 命令行方式监控GC
1、Linux下使用命令:which java, 找到JDK目录;
2、在JDK的bin目录下,使用命令:jps 查看JVM进程PID。 或者也可以使用:
ps -ef | grep java
查看Java进程PID,信息也更多一些;
3、使用命令: jstat -gc 18004 1000 即可监控GC情况。其中: 18004是JAVA进程的端口号, 1000表示1000毫秒,也就是每隔一秒展示GC监控数据;
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:Eden区的大小
EU:Eden区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC: 压缩类空间大小
CCSU: 压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
2.2 图形化方式监控GC
1、xshell 登录远程服务器,输入命令:which java, 找到Java的目录在哪里。
2、到Java目录下的/jre/lib/security下,修改 java.policy这个文件的内容:
vim java.policy,
在文件末尾的 }; 前添加 permission java.security.AllPermission。
3、到Java目录的bin目录下,比如:/usr/java/jdk1.8.0_60/bin, 执行下面的命令,开启jstatd:
./jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=xx.xx.xx.xx &
xx.xx.xx.xx是你远程服务器的IP。
4、本地java安装目录下:
C:\Program Files\Java\jdk1.7.0_80\bin,
运行jvisualvm.exe,
添加远程主机,VisualVM会自动检测到jstatd连接并添加节点。
三、JVM GC优化
3.1 什么时候需要开始GC优化?
1、如果你没有设定过JVM参数,使用的是默认参数,而系统充斥着大量的超时日志时,你就需要在你的系统中进行GC优化了;
2、在检查GC状态的过程中,你应该分析监控结果以便决定是否进行GC优化,如果分析结果表明执行GC的时间只有0.1-0.3秒,那你就没必要浪费时间去进行GC优化。但是,如果GC的执行时间是1-3秒,或者超过10秒,GC将势在必行;
3、但是,你需要时刻铭记一条:GC优化永远是最后一项任务。当出现性能问题时,如果你已经设置过JVM参数,那么GC优化永远不应该是第一优先选项,先排除服务器、数据库、程序代码常见性能问题后,再着手监控优化GC也不迟。
3.2 GC优化的目的
GC优化的主要目的有两个:
1、将转移到老年代的对象数量降低到最小;
2、减少full GC的执行时间;
为了达到上面的目的,一般地,你需要做的事情有:
1、减少使用全局变量和大对象(应用代码层面);
2、调整新生代的大小到最合适(JVM参数);
3、设置老年代的大小为最合适(JVM参数) ;
4、选择合适的GC收集器(JVM参数) ;
3.3 GC优化的步骤
1、监控GC状态:
首先你需要监控GC来检查在系统执行过程中GC的各种状态;
2、分析监控结果,决定是否进行GC优化:
分析监控结果,判断是优化应用程序代码 OR 优化JVM参数 OR 代码&参数都优化。代码优化就交给开发大哥自己玩儿去吧。参数优化看下面几条。
3、JVM参数优化:
主要为两方面:堆大小设置 和 GC收集器设置。
4、分析结果:
在调整了GC参数并持续收集24小时之后,开始对调整后结果进行分析。通过不断的调整GC收集器设置和堆大小设置找到最佳的参数配置。
5、如何最快的完成GC优化:
对比性能测试的结果应该是最快的方法,为每一台服务器设置不同的参数并监控他们的状态,强烈建议至少监控1或2天的数据。
6、网上别人的参数优化配置是否我可以照搬使用:
可以借鉴,但适合别人的服务器配置,不一定适合你的服务器配置,尤其是参数后的 value(值)是需要根据你自己的实际情况来设置的。
3.4 常用JVM参数配置实例
设置方式:
LINUX下查看Tomcat的目录:sudo find / -name tomcat, 然后到bin目录下,打开catalina.sh, 设置JAVA_OPTS=设置JVM参数;
之前某web项目的JVM优化后的参数配置如下:
JAVA_OPTS=“
-Xms512m
-Xmx6G
-Xmn3G
-XX:SurvivorRatio=4
-XX:MaxTenuringThreshold=3
-XX:ParallelGCThreads=12
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+CMSPermGenSweepingEnabled
-XX:CMSInitiatingPermOccupancyFraction=85
-XX:+DisableExplicitGC
-XX:CMSFullGCsBeforeCompaction=3
-XX:+UseCMSCompactAtFullCollection
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+CMSParallelRemarkEnabled
-XX:+CMSIncrementalMode”
各参数解释:
堆大小设置:
-Xmx6G:设置JVM最大可用内存为6G;
-Xms512m:设置JVM初始内存为512m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存;
-Xmn3G:设置年轻代大小为3G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8;
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6;
-XX:MaxTenuringThreshold=3:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
GC收集器设置:
-XX:ParallelGCThreads=12:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等;
-XX:+UseParNewGC: 设置年轻代使用ParNew收集器 。可与CMS收集同时使用;
-XX:+UseConcMarkSweepGC:设置年老代使用CMS收集器;
-XX:CMSInitiatingOccupancyFraction=75:老年代使用75%后开始CMS收集;
-XX:+CMSPermGenSweepingEnabled:允许对持久代进行GC;
-XX:CMSInitiatingPermOccupancyFraction=85:持久代使用85%后触发GC;
-XX:+DisableExplicitGC:禁用“System.gc()”, 避免程序代码手动触发FULL GC;
-XX:CMSFullGCsBeforeCompaction=3:由于CMS收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。
-XX:+UseCMSCompactAtFullCollection:在FULL GC的时候,对老年代的内存空间进行压缩。可能会影响性能,但是可以消除碎片 ;
-XX:+UseCMSInitiatingOccupancyOnly:使用手动定义初始化定义开始CMS收集,禁止自行触发CMS GC;
-XX:+CMSParallelRemarkEnabled: 降低标记停顿,减少标记耗时;
-XX:+CMSIncrementalMode:使用增量模式,在增量模式下,CMS 收集器在并发阶段,不会独占整个周期,而会周期性的暂停,唤醒应用线程,把cpu资源让给正在运行的应用
。收集器把并发阶段工作,划分为片段,安排在次级(minor) 回收之间运行。这对需要低延迟,运行在少量CPU服务器上的应用很有用。
其他常用参数设置:
-XX:NewRatio=4: 设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5。如果设置了-Xmn, 此设置无效;
-Xss128k: 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右;
-XX:MaxPermSize=16m: 设置持久代大小为16m,持久代一般默认大小为64m ;
这样配置后,基本上能达到:
系统响应时间增快;
JVM回收速度增快同时又不影响系统的响应率;
JVM内存最大化利用;
线程阻塞情况最小化;
===============================
以上就是本次的全部内容,下一篇文章,我们将主要介绍以下方面的知识:
- 什么时候开始考虑做全链路压测
- 全链路压测前梳理
- 全链路压测方法
如果对你有帮助,欢迎关注我的微信公众号:程序员杨叔,各类文章都会第一时间在上面发布,持续分享全栈测试知识干货,你的支持就是作者更新最大的动力~
猜你喜欢
- 2024-10-19 Java高频面试题之Linux(java面试 linux)
- 2024-10-19 排查GC问题常用的工具(排查问题的方式有哪些)
- 2024-10-19 开发好物推荐8之自动化部署插件,再也不用登录SSH
- 2024-10-19 20道阿里巴巴中高级java面试题详解,把这些弄懂offer拿到你手软
- 2024-10-19 Java Web实战篇:发布和运维必备的12条Linux命令
- 2024-10-19 Java工程师常用Linux命令大全(linux javac)
- 2024-10-19 玩转linux下启动jar和关闭jar方式(java程序员必看)
- 2024-10-19 超详细的EFK安装部署教程--环境准备篇
- 2024-10-19 为什么阿里架构师是这样定位Java性能问题的?这几点总结的很详细
- 2024-10-19 五千字长文带你硬磕Java线程Dump分析,没看懂来找我
- 最近发表
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- sqlset (64)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)