用jconsole分析Java进程

问题描述

运行一个Java项目时报内存溢出,修改Java启动参数-Xms2048m -Xmx4096m 后还是溢出,尝试多次后问题依然存在

用jconsole分析Java进程

解决过程

于是考虑用Java诊断工具看一下启动参数是否真的生效了

Mac上Java目录是 /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/

jconsole的位置 /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/bin/jconsole

运行jconsole就能看到可视化界面了

用jconsole分析Java进程

第一个问题是哪个进程是我应该看的呢?

解决办法就是仔细看看进程名字吧,能看懂的。还有就是把不相关的Java进程kill掉

 

这里简单分析一下这几个进程吧。

sun.tools.jconsole.JConsole 这个是jconsole的进程,显然不是我们要分析的

org.jetbrains.idea.maven.server.RemoteMaven... 这个进程是idea maven进程

用排除法来看,我们就只能监控第一个进程了

 

这时你可以做一个实验,把idea和jconsole都关掉,再重新打开jconsole,再观察一下进程情况。注意idea要彻底退出,这是看到的进程就只有jconsole了。

用jconsole分析Java进程

然后我们再把idea打开看一下进程情况

用jconsole分析Java进程

这次和最开始的情况一样了。但有个问题你想过没有,我们并没有运行应用,只是打开了IDE。这时我们什么都不做,直接运行程序,同时观察java进程的变化情况。

用jconsole分析Java进程

idea底部出现Parsing java...

用jconsole分析Java进程

 

这时观察进程,并没有新的进程生成。我们连接org.jetbrains.jps.cmdline.Launcher 看看细节

用jconsole分析Java进程

这个进程占了77%的cpu,堆内存只有600兆,而且现在已经快到头了。再看一下VM概要

用jconsole分析Java进程

说明我们最开始设置的参数没起作用。

 

这时候你肯定会问这个700是在哪配置的呢。原来它是编译器的内存参数,idea是在下图这里配置的。

用jconsole分析Java进程

这时也许你会猜到了,反复出现的内存溢出原来是编译期发生的,不是运行期。所以无论我们再怎么设置运行期Java参数,也是不起作用的。再通过jconsole看一下内存情况。

用jconsole分析Java进程

可以看出内存已经持续爆满了。

 

我们把编译期内存设置成2G,再看一下效果。这次我们不运行程序,直接看VM概要

用jconsole分析Java进程

VM参数已经变成2000了,说明我们修改的参数生效了。这次先不运行程序,而是让项目重新编译一下。

用jconsole分析Java进程

用jconsole分析Java进程

可以看到内存的情况,一路上涨,超过了1G。

 

最后我们再启动一下应用程序,再观察一下Java进程。

用jconsole分析Java进程

这次你会看到多了一个com.xxx.Application的进程,这个才是我们真正的应用程序的进程。我们再进去看一下它的内存配置。

用jconsole分析Java进程

这个才是我们最开始配置的参数。

总结一下吧

在idea运行一个项目时,它首先会编译,编译成功后才会运行。编译期和运行期都可以设置Java内存的大小,而且是在不同的地址设置的,二者不会相互代替。当然如果编译期内存溢出你却把运行期内存调大了,这显然是不起作用的。jconsole是我们本地观测Java进程信息的一个不错的工具,能看到的信息不只是文章中提到的这些,你可以自行研究。