【JVM学习笔记2】手写一段OutOfMemoryError代码,以及问题怎么排查定位

先来一段代码:

import java.util.Random;

public class Hello {

    public static void main(String[] args) {

        String name = "helloworld!";

        while (true){
            name+= name + new Random().nextInt(888888888) + new Random().nextInt(777777777);
        }
    }
}

运行之后,结果如下:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3332)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
    at java.lang.StringBuilder.append(StringBuilder.java:208)
    at Demo.Hello.main(Hello.java:12)

 

很经典的一个错误:OOM,无论是研发、运维,还是测试,都对这个错误印象超级深刻!

 

如何在IDEA中运行代码,打印GC情况:

-Xms8m -Xmx8m -XX:+PrintGCDetails
[GC (Allocation Failure) [PSYoungGen: 1536K->504K(2048K)] 1536K->764K(7680K), 0.0009173 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 2040K->498K(2048K)] 2300K->1039K(7680K), 0.0012280 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1916K->504K(2048K)] 2458K->1633K(7680K), 0.0007047 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 1935K->504K(2048K)] 3993K->3033K(7680K), 0.0006022 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 1968K->0K(2048K)] [ParOldGen: 5313K->1760K(5632K)] 7281K->1760K(7680K), [Metaspace: 3293K->3293K(1056768K)], 0.0054772 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 933K->96K(2048K)] 4549K->3712K(7680K), 0.0005351 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [PSYoungGen: 96K->128K(2048K)] 3712K->3744K(7680K), 0.0003002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 128K->0K(2048K)] [ParOldGen: 3616K->3589K(5632K)] 3744K->3589K(7680K), [Metaspace: 3299K->3299K(1056768K)], 0.0066998 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] 3589K->3589K(7680K), 0.0003907 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2048K)] [ParOldGen: 3589K->3570K(5632K)] 3589K->3570K(7680K), [Metaspace: 3299K->3299K(1056768K)], 0.0069380 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3332)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:674)
    at java.lang.StringBuilder.append(StringBuilder.java:208)
    at Demo.Hello.main(Hello.java:12)
Heap
 PSYoungGen      total 2048K, used 113K [0x00000000ffd80000, 0x0000000100000000, 0x0000000100000000)
  eden space 1536K, 7% used [0x00000000ffd80000,0x00000000ffd9c4c8,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 5632K, used 3570K [0x00000000ff800000, 0x00000000ffd80000, 0x00000000ffd80000)
  object space 5632K, 63% used [0x00000000ff800000,0x00000000ffb7c848,0x00000000ffd80000)
 Metaspace       used 3348K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 362K, capacity 388K, committed 512K, reserved 1048576K

 

可以看出,先是经过了4次YGC,然后触发了1次Full GC,同时年轻代清空。

然后年轻代不断增大,在触发了2次YGC之后,触发了第2次Full GC,此时的年轻代只有128k。

再经历了1次YGC,之后Full GC之后年轻代空,老年代仍是满的,报OOM错误信息。

 

如何排查定位问题?最简单的就是在IDEA中安装一个插件--JProfiler,然后官网下载一个客户端。

IDEA中设置运行参数:-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

依次可以定位最大的对象、出问题的代码行数!

 

 

 

posted @ 2021-01-07 15:31  愚人李愚  阅读(235)  评论(0编辑  收藏  举报