DirectByteBuffer 堆外内存高引起G1 gc cpu load高 || cpu busy

本文讨论了DirectByteBuffer引起的堆外内存问题,如何通过设置-XX:+DisableExplicitGC限制其大小,以及当堆外内存不足时如何触发Full GC。监控方法包括使用MBeanServer获取信息,配合gc dump和pmap分析,以及通过NMT定位到如GZIPInputStream未关闭导致的内存持续增长,这些问题可能导致频繁Full GC或交换分区占用过多。
摘要由CSDN通过智能技术生成
  • 对外内存监控示例

  • 设置 
    -XX:-+DisableExplicitGC 限制堆外内存大小 如果没有设置默认上限和 -Xmx 大小一致 堆外内存不够将触发full gc回收堆内对象,有引用堆外内存的对象被回收后触发finalize回收堆外内存 或者触发cleaner回收。
  • 堆外内存查看  MBeanServer获取
    MBeanServer mbs = ManagementFactory. getPlatformMBeanServer() ;
    ObjectName objectName = new ObjectName("java.nio:type=BufferPool,name=direct" ) ;
    MBeanInfo info = mbs.getMBeanInfo(objectName) ;
    for(MBeanAttributeInfo i : info.getAttributes()) {
        System.out .println(i.getName() + ":" + mbs.getAttribute(objectName , i.getName()));
    }

    gc dump 获取 配合pmap 查看指向内存的引用对象

  • JDK 获取堆外内存使用情况     /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/src.zip!/java/nio/Bits.java:730

        // -- Monitoring of direct buffer usage --
    
        static {
            // setup access to this package in SharedSecrets
            sun.misc.SharedSecrets.setJavaNioAccess(
                new sun.misc.JavaNioAccess() {
                    @Override
                    public sun.misc.JavaNioAccess.BufferPool getDirectBufferPool() {
                        return new sun.misc.JavaNioAccess.BufferPool() {
                            @Override
                            public String getName() {
                                return "direct";
                            }
                            @Override
                            public long getCount() {
                                return Bits.count.get();
                            }
                            @Override
                            public long getTotalCapacity() {
                                return Bits.totalCapacity.get();
                            }
                            @Override
                            public long getMemoryUsed() {
                                return Bits.reservedMemory.get();
                            }
                        };
                    }
                    @Override
                    public ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) {
                        return new DirectByteBuffer(addr, cap, ob);
                    }
                    @Override
                    public void truncate(Buffer buf) {
                        buf.truncate();
                    }
            });
        }

     

  • 定位
    通过NMT pmap定位到是GZIPInputStream 没有close导致的堆外内存持续增加。可能引发 堆外内存不够用 持续full gc、或者swap占用等
  •  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Run_Tortoise

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值