1. 程式人生 > 實用技巧 >【JVM學習筆記2】手寫一段OutOfMemoryError程式碼,以及問題怎麼排查定位

【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

依次可以定位最大的物件、出問題的程式碼行數!