携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
方法区异常:Java.Lang.OutOfMemoryError: Metaspace
方法区,用于存放对象的元信息,比如class相关信息,如类名、访问修饰符、常量池、字段描述、方法描述、静态变量、JIT编译后的代码等,运行时产生大量的类,会填满方法区,造成溢出。Java8之后用元空间Metaspace 取代了PermGen永久代 ,元空间使用的是本地内存。jdk后把放在永久带的字符串常量池移除了。
java.lang.OutOfMemoryError: PermGen space before jdk 1.8
java.lang.OutOfMemoryError: Metaspace after jdk 1.7
原因分析:
- 使用CGLib生成了大量的代理类,导致方法区被撑爆
- 在Java7之前,频繁的错误使用String.intern方法
- 应用长时间运行,没有重启JVM
- 加载了重复的类
解决思路:
- 检查元空间/永久代是否设置的过小 :-XX:MaxPermSize / -XX:MaxMetaspaceSize=512M
- 检查代码中是否存在大量的动态代理反射操作
- 检查是否使用CGLib生成了大量的代理类
- 重启JVM
案例分析
maven引入javassist依赖, javassist是一个高性能字节码工具。
Javassist 使 Java 字节码操作变得简单。它是一个用于在 Java 中编辑字节码的类库。它使 Java 程序可以在运行时定义新类,并在 JVM 加载它时修改类文件。与其他类似的字节码编辑器不同,Javassist 提供了两个级别的 API:源级别和字节代码级别。如果用户使用源代码级 API,则他们可以在不了解 Java 字节码规范的情况下编辑类文件。整个 API 仅使用 Java 语言的词汇表进行设计。您甚至可以以源文本的形式指定插入的字节码。Javassist 可以即时对其进行编译。另一方面,字节码级别的 API 允许用户像其他编辑器一样直接编辑类文件
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.23.1-GA</version>
</dependency>
虚拟机参数设置:-Xms200m -Xmx200m -XX:+HeapDumpOnOutOfMemoryError -XX:MaxMetaspaceSize=15m
public class Meta {
static javassist.ClassPool cp = javassist.ClassPool.getDefault();
public static void main(String[] args) throws CannotCompileException {
int i =0;
while (true){
Class c = cp.makeClass("eu.my.demo.Generated"+i++).toClass();
}
}
}
报错
java.lang.OutOfMemoryError: Metaspace
Dumping heap to java_pid89312.hprof ...
Heap dump file created [50293482 bytes in 0.283 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
at javassist.util.proxy.DefineClassHelper.toClass(DefineClassHelper.java:249)
at javassist.ClassPool.toClass(ClassPool.java:1120)
at javassist.ClassPool.toClass(ClassPool.java:1083)
at javassist.ClassPool.toClass(ClassPool.java:1041)
at javassist.CtClass.toClass(CtClass.java:1278)
at org.jvm.Meta.main(Meta.java:16)
分析过程
使用MAT打开上面堆转存快照java_pid89312.hprof如下图:
总共26.9MB堆空间,
问题比较明显不停的创建class造成元空间不足,存在内存泄漏需要定位到相关代码进行修改。
推荐工具
JVM 内存分析工具 mat
1、Eclipse Memory Analyzer
阿里云 APM 产品,支持 OOM 异常关键字告警
2、ARMS
阿里 Java 在线诊断工具 Arthas(阿尔萨斯)
3、alibaba Arthas
参考文档
Eclipse Memory Analyzer Open Source Project | The Eclipse Foundation