一、构建环境
1.1创建测试类 Test.java文件
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* @author steven
* @Description
* @date 2023/7/14 13:59
*/
public class Test {
/**
* 实现,向集合中添加100万个字符串,每个字符串由100个UUID组成
*/
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
String str = "";
for (int j = 0; j < 1000; j++) {
str += UUID.randomUUID().toString();
}
list.add(str);
}
System.out.println("ok");
}
}
1.2 运行时jvm参数如下参数:
-Xms8m
-Xmx8m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=D:\software\JavaDevelopment\javatool\check_tool\dump\
-XX:+PrintGCDetails
-Xloggc:D:\software\JavaDevelopment\javatool\check_tool\dump\gc.log
我是用的idea开发工具截图如下:
1.3执行测试类代码,出现以下日志,发生了内存溢出。
java.lang.OutOfMemoryError: Java heap space
Dumping heap to D:\software\JavaDevelopment\javatool\check_tool\dump\java_pid18300.hprof ...
Heap dump file created [8129976 bytes in 0.015 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:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
at Test.main(Test.java:20)
Disconnected from the target VM, address: '127.0.0.1:58380', transport: 'socket'
Process finished with exit code 1
二、分析日志
日志分析为三部分:控制台日志、dump文件和GC日志。
2.1控制台日志(如1.3中出现的日志)
java.lang.OutOfMemoryError: Java heap space
Dumping heap to D:\software\JavaDevelopment\javatool\check_tool\dump\java_pid18300.hprof ...
Heap dump file created [8129976 bytes in 0.015 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:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
at Test.main(Test.java:20)
Disconnected from the target VM, address: '127.0.0.1:58380', transport: 'socket'
Process finished with exit code 1
堆内存溢出:Java heap space;
发生在数组扩容时期: Arrays.copyOf();
发生的业务方法 Test类20行处: at Test.main(Test.java:20)
2.1dump文件
2.1.1工具
本人推荐jvisualvm.exe 和 jprofiler 两款分析工具,其中jvisualvm在jdk中bin目录中可以找到
使用jvisualvm打开生成的dump文件 java_pid20360.hprof
点击导致 OutOfMemoryError 异常错误的线程
jprofiler 官方可以下载 Java Profiler - JProfiler
2.2分析(jvisualvm)
dump文件内容如下
"JDWP Event Helper Thread" daemon prio=10 tid=7 RUNNABLE
"Finalizer" daemon prio=8 tid=3 WAITING
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
Local Variable: java.lang.ref.ReferenceQueue#15
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
Local Variable: java.lang.System$2#1
"Signal Dispatcher" daemon prio=9 tid=4 RUNNABLE
"main" prio=5 tid=1 RUNNABLE
at java.lang.OutOfMemoryError.<init>(OutOfMemoryError.java:48)
at java.util.Arrays.copyOf(Arrays.java:3332)
Local Variable: char[]#20
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
Local Variable: java.lang.String#19
Local Variable: java.lang.StringBuilder#1
at Test.main(Test.java:20)
Local Variable: java.lang.String[]#118
Local Variable: java.util.ArrayList#23
Local Variable: java.lang.String#18
"JDWP Transport Listener: dt_socket" daemon prio=10 tid=6 RUNNABLE
"JDWP Command Reader" daemon prio=10 tid=8 RUNNABLE
"Attach Listener" daemon prio=5 tid=5 RUNNABLE
"Reference Handler" daemon prio=10 tid=2 WAITING
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
可知是数组扩容是出现的出现堆溢出Arrays.copyOf(Arrays.java:3332)
业务行Test类20行:Test.main(Test.java:20)
3.3GC日志