zoukankan      html  css  js  c++  java
  • JDK8记FullGC时候Metaspace内存不会被垃圾回收

    本文链接:https://blog.csdn.net/a15939557197/article/details/90635460
    背景
    前段时间有一个这样的需求:第三方调用接口,30分钟内调用120W次;

    物理机(与线上配置一样)上压测,第一次压了20w次,没有出现问题;接着又压了20w次,出现了内存溢出问题。

    java.lang.OutOfMemoryError: Metaspace
    JVM配置 
    JAVA_OPT_MEM="
    -server -Xms4096M -Xmx4096M -Xmn512M -XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=512M
    -XX:+UseParNewGC //新生区使用CMS(标记清理)算法进行垃圾回收
    -XX:+UseConcMarkSweepGC //新生代使用并行收集器,老年代使用 CMS+串行收集器
    ...
    ...
    "
     初始化最大元空间是512M,

      增加两个参数,在Full GC前后分别对内存做一个heap dump

    -XX:+HeapDumpBeforeFullGC
    -XX:+HeapDumpAfterFullGC
    观察GC日志

    {Heap before GC invocations=2799 (full 1):
    par new generation total 471872K, used 58664K [0x00000006c0000000, 0x00000006e0000000, 0x00000006e0000000)
    eden space 419456K, 9% used [0x00000006c0000000, 0x00000006c2679e10, 0x00000006d99a0000)
    from space 52416K, 36% used [0x00000006dccd0000, 0x00000006ddfa0218, 0x00000006e0000000)
    to space 52416K, 0% used [0x00000006d99a0000, 0x00000006d99a0000, 0x00000006dccd0000)
    concurrent mark-sweep generation total 3670016K, used 131775K [0x00000006e0000000, 0x00000007c0000000, 0x00000007c0000000)
    Metaspace used 258955K, capacity 262086K, committed 262144K, reserved 1265664K
    class space used 45934K, capacity 46565K, committed 46592K, reserved 1048576K
    2019-04-02T17:22:31.606+0800: 1359.334: [Full GC (Metadata GC Threshold) 2019-04-02T17:22:31.606+0800: 1359.334: [Heap Dump (before full gc): , 2.0610454 secs]2019-04-02T17:22:33.667+0800: 1361.395: [CMS2019-04-02T17:22:33.812+0800: 1361.540: [CMS-concurrent-mark: 0.163/2.264 secs] [Times: user=2.46 sys=0.25, real=2.26 secs]
    (concurrent mode failure): 131775K->104031K(3670016K), 0.7241683 secs]2019-04-02T17:22:34.391+0800: 1362.119: [Heap Dump (after full gc): , 1.9020867 secs] 190439K->104031K(4141888K), [Metaspace: 258955K->258955K(1265664K)], 4.6899705 secs] [Times: user=4.35 sys=0.49, real=4.69 secs]
    Heap after GC invocations=2800 (full 2):
    par new generation total 471872K, used 0K [0x00000006c0000000, 0x00000006e0000000, 0x00000006e0000000)
    eden space 419456K, 0% used [0x00000006c0000000, 0x00000006c0000000, 0x00000006d99a0000)
    from space 52416K, 0% used [0x00000006dccd0000, 0x00000006dccd0000, 0x00000006e0000000)
    to space 52416K, 0% used [0x00000006d99a0000, 0x00000006d99a0000, 0x00000006dccd0000)
    concurrent mark-sweep generation total 3670016K, used 104031K [0x00000006e0000000, 0x00000007c0000000, 0x00000007c0000000)
    Metaspace used 258416K, capacity 260922K, committed 262144K, reserved 1265664K
    class space used 45826K, capacity 46371K, committed 46592K, reserved 1048576K
    }
    问题
    1、FullGC的时候 Metaspace 怎么现在变成了1.2G,设置的不是512M嘛?

    [Metaspace: 258955K->258955K(1265664K)]
    查看相关资料和官方文档后,发现Metaspace还有一个区间是Klass Metaspace,由参数-XX:CompressedClassSpaceSize进行控制,参考你假笨,笨神的博客 JVM源码分析之Metaspace解密 ;JDK8的时候 Klass Metaspace默认是1G。

    2、Metaspace 空间在GC前后为什么根本没有被垃圾回收?

    [Metaspace: 258955K->258955K(1265664K)]
    从上面的GC日志分析,我们看到了Full GC前后,Metaspace的使用变化是从258955K->258955K,说明GC根本没有进行回收垃圾;

    Metaspace主要是类的一些元数据信息,主要源于类加载器,可以使用 jstat -class pid 查看类的加载和写在情况;

    还可以使用 jmap -histo:live pid  查看ClassLoader对象比较多的类型;

    Metaspace中类的元数据信息只有在加载它的ClassLoader被释放后才会发生写在,如果ClassLoader对象一直存活,那么它所加载的类的元数据信息将不会被卸载。

    参考笨神的博客 JVM源码分析之JDK8下的僵尸(无法回收)类加载器 ,摘取重要的信息如下:

    类加载器创建过多,带来的一个问题是,在类加载器第一次加载类的时候,会在Metaspace里会给它分配内存块,为了分配高效,每个类加载器用来存放类信息的内存块都是独立的,所以哪怕你这个类加载器只加载一个类,也会为之分配一块空的内存给这个类加载器,其实是至少两个内存块,于是你有可能会发现Metaspace的内存使用率非常低,但是committed的内存已经达到了阈值,从而触发了Full GC,如果这种只加载很少类的类加载器非常多,那造成的后果就是很多碎片化的内存。

    处理办法
    修改代码使用反射完成对象之间属性的copy,改为set方法进行实现,解决了该问题;

    总结
    如果项目中有大流量的调用接口,一定要警惕大流量带来的大量反射类加载器创建引起的GC不回收问题。
    ————————————————
    版权声明:本文为CSDN博主「沿途风景21」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/a15939557197/article/details/90635460

  • 相关阅读:
    flexigrid 分析
    [转]使IE浏览器支持CSS3属性(圆角、阴影、渐变)
    mojoPortal 笔记
    简易的Json转换的实现
    关于 base64 编码不适用web的改进
    无法删除表,提示被外键约束引用的解决
    HTML 自适应高度的Js 算法
    从网页中提取出所有的电子邮件
    sqlserver 聚合函数
    调试MVC4的方法
  • 原文地址:https://www.cnblogs.com/jjj250/p/11995180.html
Copyright © 2011-2022 走看看