GC之DirectBuffer

// -- Direct memory management --
    // A user-settable upper limit on the maximum amount of allocatable
    // direct buffer memory.  This value may be changed during VM
    // initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
    private static volatile long maxMemory = VM.maxDirectMemory();
    private static volatile long reservedMemory;
    private static volatile long totalCapacity;
    private static volatile long count;
    private static boolean memoryLimitSet = false;
    // These methods should be called whenever direct memory is allocated or
    // freed.  They allow the user to control the amount of direct memory
    // which a process may access.  All sizes are specified in bytes.
    static void reserveMemory(long size, int cap) {
        synchronized (Bits.class) {
            if (!memoryLimitSet && VM.isBooted()) {
                maxMemory = VM.maxDirectMemory();
                memoryLimitSet = true;
            }
            // -XX:MaxDirectMemorySize limits the total capacity rather than the
            // actual memory usage, which will differ when buffers are page
            // aligned.
            if (cap <= maxMemory - totalCapacity) {
                reservedMemory += size;
                totalCapacity += cap;
                count++;
                return;
            }
        }
        System.gc();
        try {
            Thread.sleep(100);
        } catch (InterruptedException x) {
            // Restore interrupt status
            Thread.currentThread().interrupt();
        }
        synchronized (Bits.class) {
            if (totalCapacity + cap > maxMemory)
                throw new OutOfMemoryError("Direct buffer memory");
            reservedMemory += size;
            totalCapacity += cap;
            count++;
        }
    }

System.gc()不一定都会立刻去做GC,也不一定会去做GC。

/**
 * -XX:MaxDirectMemorySize=256m -XX:+PrintGCDetails -XX:+DisableExplicitGC
 * 如果不设置此参数,默认是Xmx-Survivor大小
 * @author xixicat
 * @created 2014-10-03
 */
public class ByteBufferOOM {
    //-XX:MaxDirectMemorySize=256m
    public static void main(String []args) {
        //直接OOM
//        ByteBuffer.allocateDirect(257 * 1024 * 1024);
        //先申请256M,再申请1M,是不会OOM的,如果加上-XX:+DisableExplicitGC则OOM
        ByteBuffer.allocateDirect(256 * 1024 * 1024);
        //这里直接GC
        ByteBuffer.allocateDirect(1024 * 1024);
    }
}

禁用显示GC后,发现DirectBuffer满后不会触发FullGC,直接发生OOM

如果增加一个引用,第一次分配256M,则直接OOM

import sun.nio.ch.DirectBuffer;
import java.nio.ByteBuffer;
/**
 * -XX:MaxDirectMemorySize=256m -XX:+PrintGCDetails
 * -XX:+DisableExplicitGC
 * 如果不设置此参数,默认是Xmx-Survivor大小
 * @author xixicat
 * @created 2014-10-03
 */
public class ByteBufferOOM {
    public static void directOOM(){
        //直接OOM
        ByteBuffer.allocateDirect(257 * 1024 * 1024);
    }
    public static void fullGC(){
        //先申请256M,再申请1M,是不会OOM的
        ByteBuffer.allocateDirect(256 * 1024 * 1024);
        //这里直接GC
        ByteBuffer.allocateDirect(1024 * 1024);
    }
    public static void disableGCOOM(){
        //加上-XX:+DisableExplicitGC则OOM
        ByteBuffer.allocateDirect(256 * 1024 * 1024);
        ByteBuffer.allocateDirect(1024 * 1024);
    }
    public static void gcReference(){
        //增加引用,则直接OOM
        //Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
        //DirectBuffer的GC规则与堆对象的回收规则一样,只有垃圾对象才被回收,而判定是否为垃圾对象
        //依据引用树中的存活节点来判定
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(256 * 1024 * 1024);
        ByteBuffer.allocateDirect(1024 * 1024);
    }
    public static void manualClear(){
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(256 * 1024 * 1024);
        //手工释放,无需等到GC才释放,这个时候可以直接禁用显示GC
        ((DirectBuffer)byteBuffer).cleaner().clean();
        ByteBuffer.allocateDirect(1024 * 1024);
    }
    public static void main(String []args) {
//        directOOM();
//        fullGC();
//        disableGCOOM();
//        gcReference();
        manualClear();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值