简介
最近在工作中偶尔会遇到一些Java应用的内存问题,比如内存的持续增长,或者相关的内存溢出问题。如果没有相关的经验或对相关工具的使用不太熟悉,可能看问题就会比较慢。(当然这种问题一般也不是那么好就直接看出来的)因此做一些总结和简单的分享。
相关工具
-
生成快照
首先,当问题出现时,往往表现为我们的监控指标异常(内存使用量突然提升或持续提升),或者应用的响应时间缓慢甚至超时。这时我们可以访问到我们的服务器上,查看是哪些进程导致了这样的异常。比如,你可以使用top命令,看到cpu/memory比较高的进程,选择性地进行排查。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
15558 root 20 0 11.9g 1.9g 7612 S 138.0 2.0 20033:35 java
7132 root 20 0 20.0g 8.5g 7844 S 115.8 9.1 21906:23 java
根据异常进程对应的PID,我们可以使用jmap命令打印他当前的快照。生成的.hprof文件就是对应的内存快照文件。
jmap -dump:format=b,file=heapdump.hprof PID
jmap:这是Java Memory Map工具的命令,它是JDK提供的一个命令行工具,用于生成堆转储和查看Java堆信息。
-dump:这个选项告诉jmap工具执行堆转储操作。
format=b:这个参数指定了转储文件的格式为二进制(b代表binary)。
file=wes-heapdump.hprof:这个参数指定了转储文件的名称和路径。在这个例子中,文件名被指定为wes-heapdump.hprof。
PID:这是要生成堆转储的Java进程的进程ID。你需要将PID替换为实际的进程ID数字。
有了快照文件,我们就可以将他导入到分析工具中进行分析了。
-
jvisualVM
在JDK的安装路径的bin目录下,我们可以找到jvisualVM
双击打开后,在左上角选择 文件->装入,选择刚刚生成的.hprof文件,即可将其导入visualvm进行分析。
-
Profiler
visualvm虽然在很多时候可以解决很多问题,但是在我的情况下,我的.hprof文件已经高达20多个G,点导入以后他会直接报内存不足的错。即使我调了参数,加载起来依然非常慢。所以在等待他加载的间隙使用了IntelliJ IDEA自带的工具profiler进行分析。
profiler默认应该是隐藏的,你可以在左边的...中找到他。打开以后,他会显示当前机器中正在运行的程序的Java进程的简略信息
点击这些个进程可以直接对当前进程进行分析。但是我们是导出的dump文件,所以应该点击右侧的open snapshot 按钮进行导入。
导入的时候他可能会提示内存不足之类的信息。这时你可以尝试把IDEA分配的heap内存调高一点。
等待一段时间后,其默认将展示其对应的class的基本信息与内存占用情况。
在右侧可以看到,有Biggest Objects、GC ROOT等选项,我们点击calculate,查看大对象。观察对象的使用情况是否有异常,以判断应用是否有内存溢出的情况发生。
-
Memary Analyze Tool
虽然IDEA的profiler已经基本上可以满足我们的需要,但是如果内存溢出的现象不明显,我们需要对比多个时间点的快照进行分析,那MAT可能是更适合的选择。
MAT基于eclipse,其有丰富的内存分析的功能。其使用也很方便,直接在左上角导入我们的dump文件,就可以看到内存的全局的概览。
下方的推荐选项中包括了生成图标、查看大对象、内存溢出报告等实用功能,直接根据引导使用即可。