FAQ-java.lang.OutOfMemoryError: Metaspace

问题描述/异常栈

2022-12-02T10:01:09.358+0800: [Full GC (Last ditch collection) [PSYoungGen: 0K->0K(1864192K)] [ParOldGen: 2775805K->2769090K(5592576K)] 2775805K->2769090K(7456768K), [Metaspace: 129208K->128072K(1163264K)], 0.7083895 secs] [Times: user=14.10 sys=1.02, real=0.71 secs] 
2022-12-02 10:01:10 CST BlockManagerInfo INFO - Removed broadcast_24_piece21 on aaaaaa.bbbbbb.com:40052 on disk (size: 4.0 MB)
2022-12-02 10:01:10 CST BlockManagerInfo INFO - Removed broadcast_24_piece15 on aaaaaa.bbbbbb.com:40052 on disk (size: 4.0 MB)
2022-12-02 10:01:10 CST BlockManagerInfo INFO - Removed broadcast_24_piece19 on aaaaaa.bbbbbb.com:40052 on disk (size: 4.0 MB)
#
# java.lang.OutOfMemoryError: Metaspace
# -XX:OnOutOfMemoryError="kill -9 %p"
#   Executing /bin/sh -c "kill -9 92652"...

问题原因

java.lang.OutOfMemoryError: Metaspace 错误所表达的信息是: 元数据区(Metaspace) 已被用满

Java8中,将之前 PermGen 中的所有内容, 都移到了 Metaspace 空间。例如: class 名称, 字段, 方法, 字节码, 常量池, JIT优化代码, 等等。

Metaspace 的使用量与JVM加载到内存中的 class 数量/大小有关。可以说, java.lang.OutOfMemoryError: Metaspace 错误的主要原因, 是加载到内存中的 class 数量太多或者体积太大。

目前我们 Spark 默认的配置的 MaxMetaspaceSize 大小是 128m 从上面的报错日志中打印的 Full GC 信息中也可以看出来,目前 GC  Metaspace 已经使用到了 128072K125M)达到了瓶颈,接下来就报出了 java.lang.OutOfMemoryError: Metaspace 错误。

解决方案

如果抛出与 Metaspace 有关的 OutOfMemoryError , 第一解决方案是增加 Metaspace 的大小,调整下列参数中的MaxMetaspaceSize值:
conf.spark.driver.extraJavaOptions -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m -XX:OnOutOfMemoryError="kill -9 %p" -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution

作者:denglaixiang