jmap MAT記憶體溢位實踐
jmap MAT記憶體溢位實踐
一、建立Spring Boot工程
進入https://start.spring.io/網站,配置如下圖
點選建立工程,然後用Idea或者Eclipse開啟
二、建立模擬Heap記憶體溢位的程式碼
1、建立MemoryController類
2、建立User類
public class User { private int id; private String name; public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
3、 設定最大記憶體和最小記憶體為32M
-Xmx32M -Xms32M
4、執行工程
http://127.0.0.1:8080/heap
出現記憶體溢位
三、建立模擬非Heap記憶體溢位
1、引入asm
<dependency> <groupId>asm</groupId> <artifactId>asm</artifactId> <version>3.3.1</version> </dependency>
2、建立Metaspace類
/** * https://blog.csdn.net/bolg_hero/article/details/78189621 * 繼承ClassLoader是為了方便呼叫defineClass方法,因為該方法的定義為protected */ public class Metaspace extends ClassLoader{ public static List<Class<?>> createClasses() { // 類持有 List<Class<?>> classes = new ArrayList<Class<?>>(); // 迴圈1000w次生成1000w個不同的類。 for (int i = 0; i < 10000000; ++i) { ClassWriter cw = new ClassWriter(0); // 定義一個類名稱為Class{i},它的訪問域為public,父類為java.lang.Object,不實現任何介面 cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null, "java/lang/Object", null); // 定義建構函式<init>方法 MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); // 第一個指令為載入this mw.visitVarInsn(Opcodes.ALOAD, 0); // 第二個指令為呼叫父類Object的建構函式 mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); // 第三條指令為return mw.visitInsn(Opcodes.RETURN); mw.visitMaxs(1, 1); mw.visitEnd(); Metaspace test = new Metaspace(); byte[] code = cw.toByteArray(); // 定義類 Class<?> exampleClass = test.defineClass("Class" + i, code, 0, code.length); classes.add(exampleClass); } return classes; } }
3、建立呼叫方式
private List<Class<?>> classList = new ArrayList<>();
/** * -XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M * * @return */ @GetMapping("/nonheap") public String nonheap(){ while (true){ classList.addAll(Metaspace.createClasses()); } }
4、設定JVM引數
-XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M
5、啟動呼叫
http://127.0.0.1:8080/nonheap
發現記憶體溢位
Exception in thread "http-nio-8080-exec-4" java.lang.OutOfMemoryError: Metaspace
四、解決方法
如果生成環境出現記憶體溢位,應該如何解決呢
1、匯出記憶體映像檔案
1)記憶體溢位自動匯出
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
配置如下
-Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./
然後呼叫http://localhost:8080/heap
顯示hprof檔案已經生成了
2)使用jmap命令手動匯出
jmap -dump:format=b,file=heap.hprof 15296
15296是tomcat的程序。 這樣就生成了一個heap.hprof 檔案
jmap -heap 5579 檢視記憶體的使用,每個區塊佔有多少記憶體(5579是tomcat的程序)
2、MAT分析記憶體映像檔案
現在MAT工具 http://www.eclipse.org/mat/downloads.php
我這裡下載的是Windows (x86_64)版本
然後使用這個工具開啟剛才生成的hprof檔案