发布网友 发布时间:2022-11-29 04:33
共1个回答
热心网友 时间:2023-10-26 09:44
这几天生产上有台机器的Metaspace一直在告警,Metaspace使用达到了97%。使用 -XX:MetaspaceSize=512m ,告警也还在在持续,查看MC只有81536.0,显然这个参数没起作用。
也有人遇到类似的问题,并在openjdk上提过类似的bug,其实是一个注释的bug,最终在 JDK-8151845 中修复了。
查看了Oracle的手册,Metaspace的GC会在committed size达到high-water mark之后发生。并且GC之后high-water mark会变化:变大或者变小,变大的话会防止下次GC发生得太早。high-water mark的默认初始大小20.8M,通过MetaspaceSize来设置,可见MetaspaceSize是控制Metaspace发生GC的阈值。GC后high-water mark的变化,通过MaxMetaspaceFreeRatio和MinMetaspaceFreeRatio控制。
"类元数据在卸载相应的Java类时被解除分配。由于垃圾回收,Java类被卸载,并且可以诱导垃圾回收来卸载类并解除分配类元数据。当为类元数据提交的空间达到某个级别 (高水位线) 时,将诱导垃圾收集。在垃圾回收之后,根据从类元数据中释放的空间量,可以提高或降低高水位线。高水位线将被提高,以免过早引发另一次垃圾收集。高水位标记最初设置为命令行选项-XX:MetaspaceSize的值。[...]-XX:MetaspaceSize的默认大小取决于平台,范围从12 MB到大约20 MB。”
MaxMetaspaceSize默认为-1,无限大。不过如果没有*的话,一直增大会被系统干掉进程。最好还是设置一下,比如1G。
下面是我测试了分别设置MetaspaceSize、MaxMetaspaceSize、InitialBootClassLoaderMetaspaceSize为1G,Metaspace的变化。
-XX:MetaspaceSize=1024m
-XX:MaxMetaspaceSize=1024m
-XX:InitialBootClassLoaderMetaspaceSize=1024m
三个参数都是没有改变init的大小,但是InitialBootClassLoaderMetaspaceSize改变了committed的大小,其实也是最终我们要的设置。
关于这个参数,可以看你假笨的关于 Metaspace的源码解读 ,发现的有点晚了。
最后的解决方案是使用这个配置: -XX:MaxMetaspaceSize=1024m -XX:InitialBootClassLoaderMetaspaceSize=256m 。