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中这部分空间直接消耗物理内存,元空间消耗不是很明显察觉,可以适当减小元空间大小可以比较快看出元空间消耗的变化。

目录
相关文章
|
7月前
|
Java iOS开发 MacOS
8 种 Java- 内存溢出之四 -Metaspace
8 种 Java- 内存溢出之四 -Metaspace
|
5月前
|
存储 Java 程序员
Java面试题:请解释Java中的永久代(PermGen)和元空间(Metaspace)的区别
Java面试题:请解释Java中的永久代(PermGen)和元空间(Metaspace)的区别
225 11
|
11天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
19天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
2天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
2天前
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
20 1
|
10天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
|
10天前
|
Java 开发者
Java多线程编程的艺术与实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的技术文档,本文以实战为导向,通过生动的实例和详尽的代码解析,引领读者领略多线程编程的魅力,掌握其在提升应用性能、优化资源利用方面的关键作用。无论你是Java初学者还是有一定经验的开发者,本文都将为你打开多线程编程的新视角。 ####
|
9天前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####