8 种 Java- 内存溢出之四 -Metaspace

简介: 8 种 Java- 内存溢出之四 -Metaspace

4.1 java.lang.OutOfMemoryError: Metaspace 概述

Java 应用只允许使用有限的内存. 你的应用可以用的准确的内存大小在启动的时候指定. 展开来说, Java 内存被分成不同的区域, 具体如下图:

所有的这些区域, 包括元空间 (metaspace) 区域, 可以在 JVM 启动的时候指定. 如果你没有指定这些的大小, 平台相关的默认配置会被应用.

java.lang.OutOfMemoryError: Metaspace 消息表明 Metaspace 区内存耗尽.

4.2 原因

如果你不是 Java 领域的新手, 你可能会熟悉 Java 内存管理的另一个叫做: PermGen 的概念. 从 Java 8 开始, Java 的内存模型发生明显改变. 引入一个叫做 Metaspace 的新的内存区域, Permgen 被移除. 这个变更是基于多种原因的, 包括但不限于:

  • PermGen 需要的内存大小难以预测. 它导致有可能由于内存不足触发 java.lang.OutOfMemoryError: Permgen 错误或预留过多导致浪费资源.
  • GC 性能的提升, 在没有 GC 暂停和元数据的特定迭代器的情况下启用并发类数据分配.
  • 支持进一步优化,如 G1 并发类卸载。

所以, 如果你熟悉 PermGen, 那么你需要知道的就是 – Java 8 之前版本在 PermGen 里存在的一切东西(组成类的名字和字段, 方法的字节码, 常量池信息, 对象数组和类型数组, 以及实时编译优化) – 现在都在 Metaspace 里.

如你所见, Metaspace 大小需求取决于加载的类的数量和这些类声明的大小. 所以, 很明显 java.lang.OutOfMemoryError: Metaspace 的主要原因是: 太多类, 或太大的类被加载到 Metaspace 中.

4.3 案例

就如我们在之前解释的那样, Metaspace 使用率与加载到 JVM 中的类的数量强相关. 下列代码就是最简单的例子:

public class Metaspace {
    static javassist.ClassPool cp = javassist.ClassPool.getDefault();
 
    public static void main(String[] args throws Exception {
        for (int i=0; ;i++) {
            Class c = cp.makeClass("eu.plumbr.demo.Generated" + i).toClass();
        }
    }
}
JAVA

在这个例子中, 源代码循环遍历一个循环并在运行时生成类. 所有这些生成的类定义在持续地消耗 Metaspace. javassist库对类生成的复杂性进行了处理.

代码会持续生成新的类, 并加载他们的定义到 Metaspace 中直到空间被完全占满, java.lang.OutOfMemoryError: Metaspace抛出. 当在 Mac OS X, Java 1.8.0_05 上使用 -XX:MaxMetaspaceSize=64m 大概加载 70,000 个类会死掉.

4.4 解决方案

第一个解决因为 Metaspace 内存溢出的方案很明显. 如果应用耗尽了 Metaspace 的内存, 你应该增加 Metaspace 的大小. 调整应用运行配置, 调整下列参数:

-XX:MaxMetaspaceSize=512m

上述配置案例告诉 JVM, Metaspace 允许在抛出 OutOfMemoryError 的错误之前增长到 512MB.

另一个解决方案乍一看更容易. 你可以通过删除这个参数移除 Metaspace 的限制. 但是需要注意的是, 你这么做, 可能会导致 swap 的大量消耗和 / 或导致本机物理内存分配失败.

通过使用上述建议的 “快速修复”, 你只会通过隐藏 java.lang.OutOfMemoryError: Metaspace掩盖症状, 而不是从根本上解决问题.

如果应用程序内存泄漏或是加载的不合理的东西到 Metaspace, 上述解决方案实际上不会改善任何事情, 它只会推迟问题。

相关文章
|
15天前
|
存储 Java 编译器
Java内存区域详解
Java内存区域详解
29 0
Java内存区域详解
|
25天前
|
缓存 算法 Java
Java内存管理与调优:释放应用潜能的关键
【4月更文挑战第2天】Java内存管理关乎性能与稳定性。理解JVM内存结构,如堆和栈,是优化基础。内存泄漏是常见问题,需谨慎管理对象生命周期,并使用工具如VisualVM检测。有效字符串处理、选择合适数据结构和算法能提升效率。垃圾回收自动回收内存,但策略调整影响性能,如选择不同类型的垃圾回收器。其他优化包括调整堆大小、使用对象池和缓存。掌握这些技巧,开发者能优化应用,提升系统性能。
|
1月前
|
监控 Java 数据库连接
解析与预防:Java中的内存泄漏问题
解析与预防:Java中的内存泄漏问题
|
22天前
|
缓存 安全 Java
Java并发编程进阶:深入理解Java内存模型
【4月更文挑战第6天】Java内存模型(JMM)是多线程编程的关键,定义了线程间共享变量读写的规则,确保数据一致性和可见性。主要包括原子性、可见性和有序性三大特性。Happens-Before原则规定操作顺序,内存屏障和锁则保障这些原则的实施。理解JMM和相关机制对于编写线程安全、高性能的Java并发程序至关重要。
|
29天前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
81 0
|
2月前
|
存储 安全 Java
一文带你读懂深入理解Java内存模型
java内存模型(Java Memory Model,JMM)是java虚拟机规范定义的,用来屏蔽掉java程序在各种不同的硬件和操作系统对内存的访问的差异,这样就可以实现java程序在各种不同的平台上都能达到内存访问的一致性。可以避免像c++等直接使用物理硬件和操作系统的内存模型在不同操作系统和硬件平台下表现不同,比如有些c/c++程序可能在windows平台运行正常,而在linux平台却运行有问题。 物理硬件和内存
21 1
|
4天前
|
Java 程序员 数据库连接
Java从入门到精通:3.3.2性能优化与调优——内存管理篇
Java从入门到精通:3.3.2性能优化与调优——内存管理篇
Java从入门到精通:3.3.2性能优化与调优——内存管理篇
|
4天前
|
存储 安全 Java
滚雪球学Java(19):JavaSE中的内存管理:你所不知道的秘密
【4月更文挑战第8天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
30 4
滚雪球学Java(19):JavaSE中的内存管理:你所不知道的秘密
|
12天前
|
存储 缓存 监控
Java内存管理:垃圾回收与内存泄漏
【4月更文挑战第16天】本文探讨了Java的内存管理机制,重点在于垃圾回收和内存泄漏。垃圾回收通过标记-清除过程回收无用对象,Java提供了多种GC类型,如Serial、Parallel、CMS和G1。内存泄漏导致内存无法释放,常见原因包括静态集合、监听器、内部类、未关闭资源和缓存。内存泄漏影响性能,可能导致应用崩溃。避免内存泄漏的策略包括代码审查、使用分析工具、合理设计和及时释放资源。理解这些原理对开发高性能Java应用至关重要。
|
20天前
|
存储 缓存 安全
【企业级理解】高效并发之Java内存模型
【企业级理解】高效并发之Java内存模型

热门文章

最新文章