JVM 性能调优总结
JVM 内存分区理解
java 内存区分为两个区,一个是堆区,一个是元空间,也叫方法区
堆区又分为年轻代和年老代
年轻代里又分了伊甸园区和幸存者区。
如图所示:
JVM 各区的作用
Eden中存放着新生成的对象,当Eden区满了之后,会触发yong gc, 将有用对象转移到幸存者区 S0区,将无用的对象销毁,释放内存空间。
当幸存者S0区满了以后,会触发yong gc,建有用的对象转移到S1区,同时销毁无用的对象,如此循环往复就是yong gc的触发机制,通常情况下,S0和S1区会有一个为0,证明内存回收正常,如果两个都不为0则可能是有内存泄漏导致对象不能被有效回收,一直占据内存所致。
Tenured区存放的是持久活跃的对象,JVM中默认对活跃对象的定义是每次yong gc后如果对象仍然存活则count +1, 当count=15后对象还存活,则为活跃对象,此时JVM会将对象从幸存者区转移到Tenured区,当yong区内存满了以后,会触发full gc,将活跃对象转移到年老代中,full gc是对整个内存的重排,会导致应用出现一定的迟缓,所以应尽量避免full gc.
在linux上使用free命令可以查看内存使用情况
top命令可以查看进程的内存消耗情况
查看java内存泄露工具
- jstat 命令
Java自带有很多内存监控工具,jstat就是其中一个,在jdk安装目录的bin目录下有jstat这个命令文件,
使用jstat可以查看内存使用或回收的情况,如:
sudo jstat -gcutil [PID] [interval].
PID是程序运行的进程ID,
interval是每隔多久打印一次,单位是毫秒。
S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E:年轻代中Eden(伊甸园)已使用的占当前容量百分比
O:old代已使用的占当前容量百分比
M:元数据区已使用的占当前容量百分比
CCS:压缩类空间已使用的占当前容量百分比
YGC :从应用程序启动到采样时年轻代中gc次数
YGCT :从应用程序启动到采样时年轻代中gc所用时间(s)
FGC :从应用程序启动到采样时old代(全gc)gc次数
FGCT :从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
那么如何算出每次yong gc的时间呢,根据jstat命令打印出的gc情况,查找gc发生的时间点,用后一个时间减去前一个时间,则是一次gc的时间,如下图示:
这里的一次gc时间是0.022毫秒,S0从0变成92.8, s1则从87.66变成0,同时gc总次数+1, yong gc时间从152.100变为152.122.
更多的jstat参数请参考百度资料。
-
jmap 命令
jmap命令也是JDK 自带的一个命令,用于生成JVM的堆转储快照dump文件或显示JVM内存映像。
我通常用他来dump堆内存快照。此命令也在jdk的bin目录下可以找到
sudo jmap -dump: [live,] format=b,file=heap.hprof [PID]
-dump: 生成JVM此时的内存快照dump文件。
live: 只转储堆中的存活对象,可选参数。
format=b: 以二进制形式转储内存快照。
file: 生成dump文件的路径
PID: 需要dump的java进程ID。 -
Memory Analysis 内存查看工具
Memory Analysis是一款便捷的内存分析工具,提供了强大的内存分析功能,可以单独下载使用,亦可以直接在Eclipse中安装对应的插件.
这里以eclipse插件为例:
eclipse > help > eclipse marketplace
搜索memory analysis
找到对应插件,安装即可,
安装完成后,在eclipse > perspective > open perspective > other中打开memory analysis.
然后在file菜单中导入dump文件 (heap.hprof)即可查看对应的内存情况。