一些JVM内存工具,记录一下

发布于 2020-12-29  315 次阅读


jmap

JDK自带了一些工具可以帮助我们查看JVM运行的堆内存情况,常用的是jmap命令

打印堆的使用情况 看下我的tomcat的jvm占用情况:

 jmap -heap <pid>

那么,从这个输出中我们也可以大致看出堆的结构,分为Young Generation (年轻代) 和 Old Generation (老年代)

Young Generation又被划分为:Eden Space , From Space 和 To Space

可以看到这里To区是干净的,还未被使用,From区已经使用了50%了

打印类的实例数量、占用的内存、类的名称,通常我们并不需要看所有的,只需要看前几条即可:

 jmap -histo[:live] <pid>

win下前几行比较麻烦:

 jmap -histo 20964 | findstr/n ^^|findstr "^[1-9]: ^1[0-9]: ^2[0-9]:"

find /N ^^在每行的开头添加行号,同时findstr /r \[[0-9]\]使用正则表达式提取前1-29行。

linux下pid进程号可以通过ps -ef | grep java获取

win10的话直接在任务管理器 进程一栏就可以看到,如果没有可以在列上勾选pid显示。

linux就简单了

 jmap -histo 20964 | head

以hprof二进制格式dump堆的使用情况(PS:相当于生成一个快照,后续我们可以对这个快照文件进行分析):

 jmap -dump:live,format=b,file=heap.bin <pid>

Memory Analyzer (MAT)

文件dump下来以后,可以使用Eclipse的MAT插件进行查看

如果日常开发用的是eclipse的话,可以直接安装这个插件,如果不是的话,这个插件也可以独立运行

https://www.eclipse.org/mat/

https://www.eclipse.org/mat/downloads.php

解压之后双击MemoryAnalyzer.exe即可运行

打开刚才的heap.bin文件

可以看到下面有三个选项卡,包括可以执行的操作和报表

先看第一个Histogram 直方图

由于这里是随便运行的一个工程,并没有出现内存泄漏之类的问题,所以这里看到的都是一些基础的java类

查看引用

Dominator Tree 可以看到biggest object以及它们所占内存的比例

我们一级一级的找,可以找到源文件,然后分析代码,最终定位到问题之根源

jconsole

JConsole 是一个内置 Java 性能分析器,可以从命令行(直接输入jconsole)或在 GUI shell (jdk\bin下打开)中运行。

它用于对JVM中内存,线程和类等的监控。可使用JTop插件。它可以监控本地的jvm,也可以监控远程的jvm,也可以同时监控几个jvm。

这款工具的好处在于,占用系统资源少,而且结合Jstat,可以有效监控到java内存的变动情况,以及引起变动的原因。在项目追踪内存泄露问题时,很实用。

2.如何启动JConsole

1)如果是从命令行启动,使JDK在PATH上,运行jconsole即可。

2)如果从GUI shell启动,找到JDK安装路径,打开bin文件夹,双击jconsole。

当分析工具弹出时(取决于正在运行的Java版本以及正在运行的Java程序数量),可能会出现一个对话框,要求输入一个进程的URL来连接,也可能列出许多不同的本地Java进程(有时包含JConsole进程本身)来连接。如图所示:

想分析那个程序就双击那个进程。

3.如何设置JAVA程序运行时可以被JConsolse连接分析

本地程序(相对于开启JConsole的计算机),无需设置任何参数就可以被本地开启的JConsole连接(Java SE 6开始无需设置,之前还是需要设置运行时参数-Dcom.sun.management.jmxremote)

无认证连接(下面的设置表示:连接的端口为8999、无需认证就可以被连接)

-Djava.rmi.server.hostname=10.0.0.110(服务器IP)
-Dcom.sun.management.jmxremote.port=8999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=8999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

监控tomcat

1、 修改Tomcat的bin目录下的catalina.bat文件 其实就是添加jvm参数

JAVA_OPTS="${JAVA_OPTS} -Djava.rmi.server.hostname=192.168.56.253 -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.acccess.file=/usr/local/tomcat/bin/jconsole/jmxremote.access -Dcom.sun.management.jmxremote.password.file=/usr/local/tomcat/bin/jconsole/jmxremote.password"

注意:这里是一行,空格不合适可能会启动不了服务。

2.编辑jmxremote.access和jmxremote.password

这两个文件是在JDK里面的,可以通过%JAVA_HOME%/jre/lib/management目录找到。里面有个jmxremote.password.template文件,将其重命名为jmxremote.password,这就是控制远程连接的用户名密码的。

编辑jmxremote.password,解开注释

# Following are two commented-out entries. The "measureRole" role has
# password "QED". The "controlRole" role has password "R&D".
monitorRole QED
controlRole R&D

然后通过客户端去连接刚刚设置的地址与端口,看到远程的jvm实时情况。

 


啦啦啦!