首页 > 代码库 > 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性能分析和调优方向