模拟JVM内存泄漏

首先要了解jvm的内存结构方面的知识
简述:
堆中存放的new 对象,还有全局变量
元空间(metaspace)中存放的是class文件 比如Class和Method对象 ,也就是所谓的一些方法

asm依赖

<dependency>
            <groupId>asm</groupId>
            <artifactId>asm</artifactId>
            <version>3.3.1</version>
</dependency>

生成Class文件的类

package com.example.demo.test;
import java.util.ArrayList;
import java.util.List;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

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);
            // 定义构造函数方法
            MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "",
                    "()V", null, null);
            // 第一个指令为加载this
            mw.visitVarInsn(Opcodes.ALOAD, 0);
            // 第二个指令为调用父类Object的构造函数
            mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",
                    "", "()V");
            // 第三条指令为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;
    }
}

场景模拟

package com.example.demo.test;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@RestController
public class TestController {

    private List<User> userList = new ArrayList<>();
    private List<Class<?>> classList = new ArrayList<Class<?>>();

    /**
     * 模拟堆内存溢出的情况 -Xms32M -Xmx32M
     * Exception in thread "http-nio-8080-exec-1" java.lang.OutOfMemoryError: GC overhead limit exceeded
     */
    @GetMapping("/heap")
    public void heap(){
        int i = 0;
        while (true){
            userList.add(new User(i++, UUID.randomUUID().toString()));
        }
    }

    /**
     * 模拟元空间内存溢出 -XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M
     * Exception in thread "http-nio-8080-exec-1" java.lang.OutOfMemoryError: Metaspace
     */
    @GetMapping("/nonHeap")
    public void nonHeap(){
        int i = 0;
        while (true){
            classList.addAll(MetaSpace.createClasses());
        }
    }

}

你可能感兴趣的:(jvm)