2.8方法区内存溢出

1.8以前会导致永久代内存溢出

测试代码如下,为了演示内存溢出,运行代码时添加虚拟机参数-XX:MaxPermSize=10m

package xx;

import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;

/**
 * 演示永久代内存溢出
 * -XX:MaxPermSize=10m
 */
public class Demo1 extends ClassLoader { // 可以用来加载类的二进制字节码
    public static void main(String[] args) {
        int j = 0;
        try {
            Demo1 test = new Demo1();
            for (int i = 0; i < 10000; i++, j++) {
                // ClassWriter作用是生成类的二进制字节码
                ClassWriter cw = new ClassWriter(0);
                // 版本号,public,类名,包名,父类,接口
                cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, "Class" + i, null, "java/lang/Object", null);
                // 返回byte[]
                byte[] code = cw.toByteArray();
                // 执行了类的加载
                test.defineClass("Class" + i, code, 0, code.length);
            }
        } finally {
            System.out.println(j);
        }
    }
}

如期所料内存溢出。报错信息为java.lang.OutOfMemoryError: PermGen space

F:\Java\jdk-1.6\bin\java.exe -XX:MaxMetaspaceSize=10m "-javaagent:F:\installation\JetBrains\IntelliJ IDEA 
3435 # 运行3435次循环之后内存溢出
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:635)
    at xx.Demo1.main(Demo1.java:25)

Process finished with exit code 1

1.8以后会导致元空间内存溢出

测试代码如下,为了演示内存溢出,运行代码时添加虚拟机参数-XX:MaxMetaspaceSize=10m

package xx;

import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;

/**
 * 演示元空间内存溢出
 * -XX:MaxMetaspaceSize=10m
 */
public class Demo1 extends ClassLoader { // 可以用来加载类的二进制字节码
    public static void main(String[] args) {
        int j = 0;
        try {
            Demo1 test = new Demo1();
            for (int i = 0; i < 10000; i++, j++) {
                // ClassWriter作用是生成类的二进制字节码
                ClassWriter cw = new ClassWriter(0);
                // 版本号,public,类名,包名,父类,接口
                cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Class" + i, null, "java/lang/Object", null);
                // 返回byte[]
                byte[] code = cw.toByteArray();
                // 执行了类的加载
                test.defineClass("Class" + i, code, 0, code.length);
            }
        } finally {
            System.out.println(j);
        }
    }
}

如期所料内存溢出。报错信息为java.lang.OutOfMemoryError: Metaspace

F:\Java\jdk-1.8.0_231\bin\java.exe -XX:MaxMetaspaceSize=10m "-javaagent:F:\installation\JetBrains\IntelliJ IDEA 
3331 # 运行3331次循环之后内存溢出
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:635)
    at xx.Demo1.main(Demo1.java:25)

Process finished with exit code 1

动态产生类的场景

  • Spring

  • Mybatis

注意:Spring和Mybatis中都使用了cglib来动态生成类,cglib和ClassWriter作用相同,都是用来动态生成类

Last updated

Was this helpful?