这里有新鲜出炉的精品教程, 程序狗速度看过来!
下面小编就为大家带来一篇 JVM 心得 OOM 时的堆信息获取方法与分析小编觉得挺不错的, 现在就分享给大家, 也给大家做个参考一起跟随小编过来看看吧
JVM 的框架知识了解之后, 实际的项目里发生了 OOM 异常的话, 怎么获取以及分析异常信息后怎么分析呢
这里稍微做一下归纳
第一步, 首先通过下面两个方法的任何一种, 把发生 OOM 时的 heap 信息 dump 下来
有两个方法, 通过设置可以把 OOM 时的 dump 信息获取到:
1)方法 1: 在 JVM 的启动参数里添加如下命令
-XX:+HeapDumpOnOutOfMemoryError
2)方法 2: 在 JDK 的安装目录下, 找到 bin 目录, 然后双击执行 "jvisualvm.exe"
执行程序之后, 在视图里可以看到正在执行的 java 程序和 Java 线程 ID(PID:xxx)
右键选中 "在 OOM 时生成 dump"
第二步, 执行如下代码(本例使用方法 1 如果使用方法 2 时需要先执行代码, 再在 JvirtualVM 中选中 java 程序设置 OOM 时生成 dump):
代码的意义是每一次创建一个 1*1024*1024 大小的 int 数组在 While 中循环, 引起 Heap 的 OutOfMemory 异常发生
有一个小知识点共享下, map 进行 containsKey 的处理时, key 如果是 javabean 对象, 判断时使用的是对象的引用所以每次判断都是新的对象
最好 key 的数据类型定义为值类型等 (String 作为 key 时使用常量字符串对 String 赋值如 String key ="key", 不要用 String key = new String(key) 的形式, 这样又变成了一个引用对象了)
- package com.chong.studyparalell.jvm.heap;
- import java.util.HashMap;
- import java.util.Map;
- public class HeapLeakage {
- static class MapKey {
- Integer key;
- MapKey(Integer key) {
- this.key = key;
- }
- }
- public static void main(String[] args) {
- Map <MapKey,
- Integer[]> localMap = new HashMap();
- while (true) {
- for (int i = 0; i <10; i++) {
- try {
- Thread.sleep(100);
- } catch(Exception e) {
- e.printStackTrace();
- }
- MapKey mapKey = new MapKey(new Integer(i));
- if (!localMap.containsKey(mapKey)) {
- localMap.put(mapKey, new Integer[1 * 1024 * 1024]);
- }
- }
- }
- }
- }
日志如下:
- JAVAGENT: call premain instrumentation for class SizeOf
- java.lang.OutOfMemoryError: Java heap space
- Dumping heap to java_pid31512.hprof ...
- Heap dump file created [491663234 bytes in 0.930 secs]
- Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
- at com.chong.studyparalell.jvm.heap.HeapLeakage.main(HeapLeakage.java:38)
第三步, 在项目的 classpath 目录下确认 "java_pidXXX.hprof" 文件是否存在, 正常情况下应该存在的
在 jvirtualvm 中, 点击 "文件"->"装入"->选中上述 hprof 文件
点击类 tab 页, 通过 "大小" 排序, 可以看出 java.lang.Integer 占用了 99% 以上的空间
双击这一行, 可以进入进去看到, 各个 Integer 的具体内容这里的目的是发生 OOM, 所以 Integer 的内容没有设值, 进去可以发现值都是 null
那么实际的项目里, 可以观看发生问题线程里哪些对象的一直是活着的, 并且 size 远远超出预期, 重点分析这些可疑对象推测的方向: 是否在循环里大量的实例化对象, 加载 DB 数据时一次加载了大量的数据, 以及是否发生了内存泄露(如长生命周期的 Map 和 Set,List 中一直保存在大量的不再使用的对象引用), 以及静态变量的使用等
后记:
通过这几天的 JVM 复习, 以及 OOM 发生时的 dump 分析, 再次做项目时, 头脑会更清晰一些 ^-^
JVM 告一段落了, 接下来会发一些跟 SpringBoot 和 Redis 相关的学习心得
来源: http://www.phperz.com/article/18/0315/352959.html