java.lang.OutOfMemoryError: Metaspace

简介: java.lang.OutOfMemoryError: Metaspace

场景说明

jdk8中把方法区实现移动到了元空间中,我们还原一次元空间溢出的场景:

import com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter;
import com.sun.xml.internal.ws.org.objectweb.asm.Opcodes;
/**
 * 永久带内存溢出
 * -XX:MapPermSize=8m jdk1.6中
 * -verbose -XX:MaxMetaspaceSize=64m
 */
public class Jvm1_8 extends ClassLoader{
    public static void main(String[] args) {
        int j=0;
        try{
            Jvm1_8 test=new Jvm1_8();
            for (int i=0;i<200000000;j++,i++){
                ClassWriter cw=new ClassWriter(0);
                cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC,"Class"+i,null,"java/lang/Object",null);
                byte[] code=cw.toByteArray();
                test.defineClass("Class"+i,code,0,code.length);
            }
        }finally {
            System.out.println(j);
        }
    }
}

代码中内容是通过动态构造类的方式生成类,这样在很短的时间内产生大量的类,由于jdk8中元空间是存放在物理内存中,短时间看不出效果,我们加上参数-XX:MaxMetaspaceSize=64m限制元空间的大小。

运行效果如下:

92706
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 Jvm1_8.main(Jvm1_8.java:18)

为了看到内部类信息的情况,我们加入-verbose参数可以显示看到类的加载情况:

-verbose -XX:MaxMetaspaceSize=64m

输出如下:

[Loaded Class92695 from __JVM_DefineClass__]
[Loaded Class92696 from __JVM_DefineClass__]
[Loaded Class92697 from __JVM_DefineClass__]
[Loaded Class92698 from __JVM_DefineClass__]
[Loaded Class92699 from __JVM_DefineClass__]
[Loaded Class92700 from __JVM_DefineClass__]
[Loaded Class92701 from __JVM_DefineClass__]
[Loaded Class92702 from __JVM_DefineClass__]
[Loaded Class92703 from __JVM_DefineClass__]
[Loaded Class92704 from __JVM_DefineClass__]
[Loaded Class92705 from __JVM_DefineClass__]
92706
[Loaded java.lang.Throwable$PrintStreamOrWriter from /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Throwable$WrappedPrintStream from /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.util.IdentityHashMap from /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.util.IdentityHashMap$KeySet from /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Shutdown from /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/lib/rt.jar]
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 Jvm1_8.main(Jvm1_8.java:17)

Process finished with exit code 1

后记

实际在很多框架中都是以动态生成类的方式去建立对象,在大量动态产生类的场景下,元空间消耗会增加,jdk8中这部分空间直接消耗物理内存,元空间消耗不是很明显察觉,可以适当减小元空间大小可以比较快看出元空间消耗的变化。

目录
相关文章
|
2月前
|
Java iOS开发 MacOS
8 种 Java- 内存溢出之四 -Metaspace
8 种 Java- 内存溢出之四 -Metaspace
|
2天前
|
监控 安全 Java
Java中的线程调度与性能优化技巧
Java中的线程调度与性能优化技巧
|
2天前
|
缓存 安全 Java
Java中的线程安全问题及解决方案
Java中的线程安全问题及解决方案
|
2天前
|
并行计算 安全 Java
Java中的多线程与并发编程详解
Java中的多线程与并发编程详解
|
2天前
|
存储 缓存 前端开发
Java八股文面试之多线程篇
Java八股文面试之多线程篇
9 0
Java八股文面试之多线程篇
|
3天前
|
并行计算 Java 大数据
Java中的高效并行计算与多线程编程技术
Java中的高效并行计算与多线程编程技术
|
4天前
|
Java 调度
Java中的线程池机制详解
Java中的线程池机制详解
|
4天前
|
并行计算 安全 Java
Java中的多线程与并发编程详解
Java中的多线程与并发编程详解
|
2天前
|
Java
java面试之线程八锁
java面试之线程八锁
7 0