1
// -- 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();
    }
}

codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...


引用和评论

0 条评论