性能文章>OOM系列之四:java.lang.OutOfMemoryError: 元空间问题详解>

OOM系列之四:java.lang.OutOfMemoryError: 元空间问题详解转载

5月前
3725218

此文来自于plumbr官网,plumbr作为一个常用的JVM 监测工具,官网有完整的oom和gc文章,准备慢慢全部翻译过来:

第一篇:java.lang.OutOfMemoryError:Java heap space

第二篇:Java.lang.OutOfMemoryError: GC overhead limit exceeded

第三篇:java.lang.OutOfMemoryError: 永久空间

第四篇:java.lang.OutOfMemoryError: 元空间

正文:

Java 应用程序只能使用有限的内存量。您的特定应用程序可以使用的确切内存量是在应用程序启动期间指定的。为了让事情变得更复杂,Java 内存被分成不同的区域,如下图所示:

元空间错误

所有这些区域的大小,包括元空间区域,都可以在 JVM 启动期间指定。如果您不自己确定大小,将使用特定于平台的默认值。

所述java.lang.OutOfMemoryError:元空间中消息指示所述元空间区域在存储器中被耗尽。

1,是什么原因造成的?

如果您不是 Java 领域的新手,您可能熟悉 Java 内存管理中的另一个概念,称为 PermGen。从 Java 8 开始,Java 中的内存模型发生了重大变化。引入了一个名为 Metaspace 的新内存区域,并删除了 Permgen。做出此更改的原因有多种,包括但不限于:

  • permgen 所需的大小很难预测。它导致供应不足触发java.lang.OutOfMemoryError: Permgen size错误或过度供应导致资源浪费。
  • GC 性能改进,启用并发类数据取消分配,无需GC 暂停和元数据上的特定迭代器
  • 支持进一步优化,例如G1并发类卸载。

因此,如果您熟悉 PermGen,那么您需要了解的背景知识就是 – Java 8 之前 PermGen 中的任何内容(类的名称和字段、类的方法以及方法的字节码、常量池、JIT 优化等) ) – 现在位于元空间。

如您所见,元空间大小要求取决于加载的类的数量以及此类声明的大小。所以很容易看到的主要原因java.lang.OutOfMemoryError:元空间是:太多的级别或过大的类加载到元空间。

2,举个例子

正如我们在前一章中解释的那样,元空间的使用与加载到 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();
		}
	}
}

在这个例子中,源代码遍历一个循环并在运行时生成类。所有这些生成的类定义最终都会消耗 Metaspace。类生成的复杂性由javassist库处理。

代码将不断生成新类并将它们的定义加载到 Metaspace,直到空间被完全利用并且java.lang.OutOfMemoryError: Metaspace被抛出。当使用-XX:MaxMetaspaceSize=64m启动时,在 Mac OS X 上,我的 Java 1.8.0_05 在加载了大约 70,000 个类时死亡。

3,解决办法是什么?

面对由于 Metaspace 导致的 OutOfMemoryError 时,第一个解决方案应该是显而易见的。如果应用程序耗尽了内存中的 Metaspace 区域,您应该增加 Metaspace 的大小。更改您的应用程序启动配置并增加以下内容:

-XX:MaxMetaspaceSize=512m

上面的配置示例告诉 JVM,允许 Metaspace 增长到 512 MB,然后才能开始以OutOfMemoryError的形式抱怨。

乍一看,另一种解决方案甚至更简单。您可以通过删除此参数来完全取消对元空间大小的限制。但请注意,这样做可能会引入大量交换和/或导致本机分配失败。

不过,在结束之前,请注意 - 通常情况下,通过使用上述推荐的“快速修复”,您最终会通过隐藏java.lang.OutOfMemoryError: Metaspace而没有解决潜在问题来掩盖症状。如果您的应用程序泄漏内存或只是将一些不合理的内容加载到 Metaspace 中,上述解决方案实际上不会改善任何事情,只会推迟问题。

请先登录,再评论

Metaspace碎片化是个头大的问题。不知道大佬有没有好的解决办法或者缓解策略吗?谢谢~

4月前

期待整个系列💪

5月前

为你推荐

JVM源码分析之Metaspace解密
概述metaspace,顾名思义,元数据空间,专门用来存元数据的,它是jdk8里特有的数据结构用来替代perm,这块空间很有自己的特点,前段时间公司这块的问题太多了,主要是因为升级了中间件所致,看到大
OutOfMemoryError之unable to create new native thread原因分析及6种解决方案
java.lang.OutOfMemoryError:unable to create new native thread 是比较常见的一种异常,表示应用程序无法创建新的线程。产生该异常,总体上可总结
java内存溢出问题分析过程
背景运维人员反馈一个容器化的java程序每跑一段时间就会出现OOM问题,重启后,间隔大概两天后复现。 问题调查 一、查日志由于是容器化部署的程序,登上主机后使用docker logs Containe
为什么容器内存占用居高不下,频频 OOM(续)
在之前的文章《[为什么容器内存占用居高不下,频频 OOM](https://heapdump.cn/article/1589003)》 中,我根据现状进行了分析和说明,收到了很多读者的建议和疑
Java OOM 实战篇:应用故障之Java heap space 堆溢出实战
以下是用于测试OOM的测试代码:```javapublic class HeapMemUseTest { public static void main(String[] args) {
一则OOM死机故障的处理过程
OOM是Out of Memory的简写,也就是内存不足。出现该问题的原因有很多,如程序内存泄漏等。内存泄漏问题可以通过定时地终止和重启有问题的程序来发现和解决。在比较新的Linux内核版本中,有一种
导致程序出现OOM的因素,夜深人静的时候,程序OOM异常追踪
作为Java程序员, 除了享受垃圾回收机制带来的便利外, 还深受OOM(Out Of Memory)的困惑和折磨。 堆溢出(heap)编写如下例程:```javapublic static void
导致程序出现OOM的因素,夜深人静的时候,程序OOM异常追踪
作为Java程序员, 除了享受垃圾回收机制带来的便利外, 还深受OOM(Out Of Memory)的困惑和折磨.先来看下java的内存分布 堆溢出(heap)编写如下例程:```javapublic