JVM和直接内存(JDK1.8)

原理

一个简单的JVM的对内存的情况如下所示。
在这里插入图片描述
可以看见,原来在堆中分配的永久代被移动到了meta区。而meta是单独的空间,使用JVM的直接内存。
然而用户其实也可以使用直接内存。
直接内存:direct/off-heap/native memory ,大家怎么叫都可以。用户可以使用如下方式使用直接内存:

使用未公开的Unsafe
NIO包下ByteBuffer。`
  • 如果使用unsafe,那就只能自己负责内存的申请和清除了
public native long allocateMemory(long bytes);
public native long reallocateMemory(long address, long bytes);
public native void freeMemory(long address);
  • 如果使用ByteBuffer。那么可以GC可以在完成队内存垃圾收集的同时帮助你清除。
    使用ByteBuffer类分配直接内存
    /**
     * Allocates a new direct byte buffer.
     *
     * <p> The new buffer's position will be zero, its limit will be its
     * capacity, its mark will be undefined, each of its elements will be
     * initialized to zero, and its byte order will be
     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.  Whether or not it has a
     * {@link #hasArray backing array} is unspecified.
     *
     * @param  capacity
     *         The new buffer's capacity, in bytes
     *
     * @return  The new byte buffer
     *
     * @throws  IllegalArgumentException
     *          If the {@code capacity} is a negative integer
     */
    public static ByteBuffer allocateDirect(int capacity) {
        return new DirectByteBuffer(capacity);
    }
    

在DirectByteBuffer中的实现其实还是依靠了UNSAFE的代码。

    DirectByteBuffer(int cap) {                   // package-private

        super(-1, 0, cap, cap);
        boolean pa = VM.isDirectMemoryPageAligned();
        int ps = Bits.pageSize();
        long size = Math.max(1L, (long)cap + (pa ? ps : 0));
        Bits.reserveMemory(size, cap);

        long base = 0;
        try {
            base = UNSAFE.allocateMemory(size);
        } catch (OutOfMemoryError x) {
            Bits.unreserveMemory(size, cap);
            throw x;
        }

在引用被消除后,会调用回掉方法,使用Unsafe代码将内存释放掉。这个是直接内存的释放的原理。

    private static class Deallocator
        implements Runnable
    {
		...
        public void run() {
            if (address == 0) {
                // Paranoia
                return;
            }
            UNSAFE.freeMemory(address);
            address = 0;
            Bits.unreserveMemory(size, capacity);
        }

    }

应用

大名鼎鼎的零拷贝技术
在这里插入图片描述
比如kafka。(注意,kafka没有用netty)

Netty

netty是对java nio的包装。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值