内存溢出之后,分析原因往往有些困难,这里在启动jvm的时候可以增加一些参数,等内存溢出发生时jvm会帮我们记录当时的快照

这是我模拟内存溢出的启动参数:

-Xmx64m -Xms32m -Xmn16m -Xss8m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/liucheng/开发/vm/VMDemo.hprof -XX:OnOutOfMemoryError="/Users/liucheng/开发/vm/sh/clear.sh VMDemo"

设置jvm的内存大小相关参数我不说了,重点是后面几个参数

-XX:+HeapDumpOnOutOfMemoryError 当jvm发生内存溢出(om溢出)的时候进行快照记录;

-XX:HeapDumpPath 设置快照路径(可以是路径,也可以是具体到快照文件名),如果不设置,默认会在当前工作空间生成快照。

-XX:OnOutOfMemoryError 设置发生内存溢出后调用一个sh脚本(调用脚本更多的目的是将快照文件转移到其他服务器,因为快照文件非常大,经常发生om又没有及时清理快照文件,会很快让磁盘被塞满)

ok,开始正题,导致堆内存溢出的代码:

java虚拟机的一些内存监控

执行结果:

java虚拟机的一些内存监控

附上clear.sh脚本:

java虚拟机的一些内存监控

生成的快照文件:

java虚拟机的一些内存监控

如何分析快照文件,这里我推荐3种方式:

一、使用java自带的命令  jhat

执行 jhat -port 8888 VMDemo.hprof
不指定 -port 默认7000
访问 http://localhost:8888

这种方式会将快照信息以web的方式展现,但是展示信息有限。

java虚拟机的一些内存监控

浏览器访问 http://localhost:7000

java虚拟机的一些内存监控

这里面每个链接操作都有相应的说明,有兴趣的可以百度了解,这种方式我不太喜欢,没有过多了解

二、使用mat工具分析

在这里下载 https://www.eclipse.org/mat/

mat载入快照文件后:

java虚拟机的一些内存监控

这个把内存情况用饼形图表达的很清楚。

更多信息

java虚拟机的一些内存监控


java虚拟机的一些内存监控

通过上面这张图可以看出代码中的 list塞入了1407条类型为string的数据

三、使用visualVM

装载进快照文件后,选择线程项

java虚拟机的一些内存监控


以上是都是快照已经生成,事后来找问题的方案,针对正在运行中的jvm来说,可以用以下方式监控jvm各种参数起到调试作用。

一、使用visualVM

这种方式我就不多说了,除了本地也可以远程连接,这种都懂,下面我要介绍的是才是好用的

java虚拟机的一些内存监控

二、使用java自带的jconsole工具

运行 jconsole 稍等一下下出来一个界面

java虚拟机的一些内存监控


这次连接一个远程的jvm来示例

远程连接之前的准备工作:

在服务器上执行 hostname -i 得到的ip应该是-Djava.rmi.server.hostname的设置ip
然后用如下命令启动:
java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9990 -Dcom.sun.management.jmxremote.rmi.port=9990 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=al.cloud.net -jar eureka-0.0.1-SNAPSHOT.jar

这里公网ip就不对外公开了,我用本地hosts  al.cloud.net映射了公网服务器ip,设置成你自己要连接的服务器上公网ip即可。

以下是参数解释

-Dcom.sun.management.jmxremote 布尔 是否支持远程JMX访问,默认true
-Dcom.sun.management.jmxremote.port 数值 监听端口号,方便远程访问
-Dcom.sun.management.jmxremote.rmi.port 数值 rmi端口,方便远程访问
-Dcom.sun.management.jmxremote.authenticate 布尔 是否需要开启用户认证,默认开启
-Dcom.sun.management.jmxremote.ssl 布尔 是否对连接开启SSL加密,默认开启
-Dcom.sun.management.jmxremote.access.file 路径 对访问用户的权限授权的文件的路径,默认路径JRE_HOME/lib/management/jmxremote.access
-Dcom.sun.management.jmxremote. password.file 路径 设置访问用户的用户名和密码,默认路径JRE_HOME/lib/management/ jmxremote.password


本地来测试一下服务器上的端口是否可以正常通信  telnet al.cloud.net 9990

开始连接

java虚拟机的一些内存监控

java虚拟机的一些内存监控

出现这个是因为ssl项设置为false了 不管它继续点击连接

java虚拟机的一些内存监控

后面的都知道操作了。

其实还有一些java自带的命令方式查看

比如:

当前线程所有堆栈信息 jstack pid
当前线程的相关信息输出到日志 kill -3 pid
查看gc信息
jstat -gc pid
  • S0C : survivor0区的总容量
  • S1C : survivor1区的总容量
  • S0U : survivor0区已使用的容量
  • S1C : survivor1区已使用的容量
  • EC : Eden区的总容量
  • EU : Eden区已使用的容量
  • OC : Old区的总容量
  • OU : Old区已使用的容量
  • PC 当前perm的容量 (KB)
  • PU perm的使用 (KB)
  • YGC : 新生代垃圾回收次数
  • YGCT : 新生代垃圾回收时间
  • FGC : 老年代垃圾回收次数
  • FGCT : 老年代垃圾回收时间
  • GCT : 垃圾回收总消耗时间

gc信息 2000ms内输出一次 总共输出20次
jstat -gc pid 2000 20

同-gc,还会输出Java堆各区域使用到的最大、最小空间
jstat -gccapacity 进程id
  • NGCMN : 新生代占用的最小空间
  • NGCMX : 新生代占用的最大空间
  • OGCMN : 老年代占用的最小空间
  • OGCMX : 老年代占用的最大空间
  • OGC:当前年老代的容量 (KB)
  • OC:当前年老代的空间 (KB)
  • PGCMN : perm占用的最小空间
  • PGCMX : perm占用的最大空间

同-gc,还会输出的是已使用空间占总空间的百分比
jstat -gcutil pid

垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因
jstat -gccause pid
  • LGCC:最近垃圾回收的原因
  • GCC:当前垃圾回收的原因
查看JIT编译过的方法数量耗时
jstat -compiler pid
  • Compiled : 编译数量
  • Failed : 编译失败数量
  • Invalid : 无效数量
  • Time : 编译耗时
  • FailedType : 失败类型
  • FailedMethod : 失败方法的全限定名
查看类装载数量
jstat -class pid
  • Loaded : 加载class的数量
  • Bytes : class字节大小
  • Unloaded : 未加载class的数量
  • Bytes : 未加载class的字节大小
  • Time : 加载时间


相关文章:

  • 2022-02-23
  • 2022-03-09
  • 2021-12-26
  • 2021-08-06
  • 2021-11-05
  • 2021-11-13
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-09-10
  • 2021-10-17
  • 2021-06-16
  • 2021-06-07
  • 2021-11-20
  • 2022-12-23
相关资源
相似解决方案