【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
依次可以定位最大的对象、出问题的代码行数!
---------------------------------------------------
立足软件测试领域,并重新定义测试!
---------------------------------------------------