最近项目中的仿真模块出现了java.lang.OutOfMemoryError:java heap space(内存不足)异常,简单查了一下,怀疑可能是内存泄露或者内存溢出;
内存泄露指的是程序中动态分配内存给一些临时对象,但是对象不会被GC(java垃圾回收机制gabage collection)所回收,它始终占用内存。即被分配的对象可达但已无用;
内存溢出指的是程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况;
从定义上可以看出内存泄露是内存溢出的一种诱因,不是唯一因素;
有时单单从代码上很难知道是哪里的问题,所以需要借助一下JDK提供的工具,实时了解程序中的资源的使用情况,JDK为我们提供了JSTATD和Java VisualVM进行远超监控:
一、启动JSTATD:在JDK的bin目录下新建jstatd.all.policy文件(其实目录可以自己选择)键入一下代码用于启动JSTATD:
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
保存;然后使用以下命令启动JSTATD:
jstatd -J-Djava.security.policy=/jstatd.all.policy文件的目录/jstatd.all.policy -p 端口号(用于Java VisualVM远程链接)
二、检查JSTATD是否已经启动
键入 jps ,如果看到jstatd已经起来了,说明启动成功;
三、在本地JDK的安装目录下bin目录,找到jvisualvm.exe文件双击打开,
打开后输入ip,端口
然后我们就可以实时的进行监控了
如果远程连接jstatd后,节点加载不出来,可以在jstatd启动时开启日志打印,方便定位问题
jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=192.168.101.56 -J-Djava.rmi.server.logCalls=true
-J-Djava.security.policy=jstatd.all.policy
=号后面的是文件的绝对路径;-J-Djava.rmi.server.logCalls=true
打开日志,如果客户端有连接过来的请求,可以监控到,便于排错;-J-Djava.rmi.server.hostname=192.168.101.56
指明本机 hostname 对应的本机地址,确保该地址可以给客户机访问。因为有的服务器 hostname 对应的 ip 不一定是外网能连上的,最好在这里直接明确指定;-p 9099
指定服务的端口号,默认是1099。也是可选参数。
注意:jstatd启动后,会开启一个随机端口,通过sudo netstat -lutnp |grep jstatd命令查看jstatd对应的端口
可以看到有个33193的端口,这个端口需要对外开放出来
sudo iptables -I INPUT -p tcp --dport 33193 -j ACCEPT
使用上面的命令开放33193端口
然后就可以通过jvisualvm远程监控了;
ps:如果需要监控GC,需要安装插件:窗体点击工具->插件->可用插件,选择需要的插件进行下载,还有插件对应的网站已经被Oracle公司关闭了,迁移到github,因此
https://visualvm.github.io/pluginscenters.html在这个网站上,找到你jdk对应的下载地址(注意小版本号),例如我的是jdk1.8.0_111,那么就是
就是这个地址,然后
jvisualvm窗体点击工具->插件->设置,点击编辑,把url改成对应的下载地址,然后进行下载,下载完需要重启jvisualvm;