一、创建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文件
原文地址:https://www.cnblogs.com/linlf03/p/10055400.html