首页 > 代码库 > JVM性能分析和调优方向
JVM性能分析和调优方向
1)合理配置参数
jvm内存=堆内存+非堆内存
堆内存=新生代+年老代 新生代=1个Eden区+2个survivo区
非堆内存=持久代+代码缓存
-server:服务器模式,该参数放置在配置项的首位置
-Xms:堆的初始大小,单位MB 配置-Xms与-Xmx一致,为可用内存的80%
-XmX:堆的最大大小,单位MB
-Xmn:新生代的初始大小,单位MB 为堆大小的3/8
当业务中有数据量很大的文件需要导出时,需要调整以下2个参数的值,可避免出现OOM
-XX:PermSize:持久代的初始大小,单位MB 为物理内存的1/64
-XX:MaxPermSize:持久代的最大大小,单位MB 为物理内存的1/4
-Xss:线程栈的大小,单位MB,如要调整,推荐1~2MB
-XX:NewRatio:年老代与新生代的比值
-XX:SurvivoRatio:Eden区与Survivo区的比值
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=path
在JVM崩溃时,可以打印出heap dump
-XX:+AggressiveOpts=false 禁用该项,可防止jdk版本升级时,jvm中加入新的优化技术
-Djava.awt.headless=true 启用该项,可解决报表不兼容的问题
-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩,启用该项可对存活对象进行整理,可减少内存碎片
-XX:+UseInitiatingOccupancyFraction=80:年老代占满80%时,开始进行CMS的垃圾回收
-XX:+DisableExplicitGC:不允许显示调用system.gc()
-XX:+UseGCOverheadLimit:当垃圾回收耗费了98%的时间,但回收的内存不到2%时,jvm认为发生了OOM,可以起到预警的作用。
-XX:+PrintGCDateStamps -verbose:gc,在日志中打印gc的详细信息
-XX:+ExplicitGCInvokesConcurrent -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses,启用该项,可减少fullgc的卡顿时间。
2)gc的过程
当1个对象生成后,会被放在新生代区域中的Eden区(young中的Eden),如果Eden区满,会触发young gc,不能被回收的对象放入s区(s0或s1),当s(s0或s1)区满后,对象会被放入年老代区域(old),如果old区满了,触发full gc,对象被放到持久代区(perm区)。
建议:尽量不要频繁的触发full gc,young gc频繁属于正常现象。
GC垃圾收集算法:
推荐设置为:并发标记清除收集器(CMS):-XX:+UseConcMarkSweepGC,多线程回收、垃圾收集时减少了卡顿时间、减少了fullgc的概率,适用于响应时间大型系统。
Serial GC(-XX:+UseSerialGC):在client模式下使用,性能最差。
Parallel GC(-XX:+UseParallelGC):多线程收集年轻代中的无效和不使用的对象,单线程收集年老代中的无效和不使用的对象
Parallel Old GC(-XX:+UseParallelOldGC):多线程收集年轻代和年老代中的无效和不使用的对象。
3)内存泄漏和系统超负荷
内存泄漏:由于错误的配置导致使用的资源无法被及时回收引起,可通过软件调优解决。
现象有:内存快要被占满,处于临界点;对应系统的日志中有出现OOM等关键字。
系统超负荷:系统中没有更多的可用资源引起,可通过更新硬件解决。
内存泄漏趋势图,其中多次GC后,多个低点的连线趋势为上升趋势,表明存在内存泄漏现象。
常见内存泄漏有:参数配置和代码2个方面
内存泄漏常见类型(配置)
1)年老代堆堆空间被占满,非常典型 异常有:java.lang.outofmemory java heap space
调整-Xms M -Xmx M 为可用内存的80% -Xmn M 为堆大小的3/8
free -m
可用内存=free+buffers+cached
2)持久代堆堆空间被占满,异常有:java.lang.outofmemory java perm space
调整-XX:PermSize= M -XX:MaxPermSize= M 1/64 1/4
3)线程栈异常:java.lang.stackoverflowerror stack size too small
调整-Xss=1M 推荐1~2M
4)系统内存被占满
java.lang.outofmemoryerror unable to create new native thread
加内存条,扩大内存大小;调整代码,减少线程的创建以降低对内存的消耗
内存泄漏常见类型(代码)
1)对象无法回收(静态类型)
2)数据库连接没有被关闭
4)使用命令监控和分析
a)查看运行于jvm上java进程的命令:jps -ml
b)查看jvm性能统计信息包括GC统计信息:jstat -gcutil 5s 5
c)查看堆内存映射信息:jmap
可打印指定java进程、核心文件、远程调用服务器的共享对象内存映射或堆内存细节
jmap -heap pid
Jmap -histo:live pid
Jmap -dump:live,format=b,file=./yyyy-mm-dd.hprof pid
d)查看线程堆栈跟踪的信息:jstack
可打印指定java进程、核心文件、远程调用服务器的线程堆栈的跟踪信息
定位和分析热点CPU的进程
jps pid
top -Hp pid 或 ps -mp pid -o THREAD,tid,time
Printf “%x\n” tid
Jstack pid |grep 16进制的tid -A 30
5)使用工具监控和分析
监控远程的tomcat服务,需要在catalina.sh中加入配置,可根据实际情况做优化配置
JAVA_OPTS="-server -Xms595M -Xmx595M -Xmn223M -XX:PermSize=10M -XX:MaxPermSize=20M”
加入配置的项。
-Djava.rmi.server.hostname=192.168.96.128
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=1235 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
工具说明:
Jconsole:可监控本地和远程机器上CPU、堆内存及各分代区内存占用、类和线程使用情况,分析是否有死锁,支持垃圾回收。
Jvisualvm:可监控本地和远程机器上CPU、堆内存、类和线程使用情况,分析是否有死锁,支持垃圾回收、线程dump、堆dump及分析线程dump、堆dump、应用快照、profile快照文件,以便发现问题。通过jmx方式连接ip:port
MemoryAnalyzer:内存分析工具,可分析jvisualvm中堆dump产生的hprof文件及jcmd dump的文件,可在打开的dump文件的详情报告中,在Thread Stack中可分析出线程是否存在死锁及其他错误。
JVM性能分析和调优方向