首页   快速返回

java堆外内存回收机制     所属分类 java
DirectByteBuffer
使用堆外内存 ,网络 IO,避免堆内存到堆外内存的数据拷贝 
Netty 使用堆外内存来实现零拷贝

java.nio.Bits 
内部维护着当前已经使用的堆外内存大小

private static volatile long maxMemory = VM.maxDirectMemory();
private static final AtomicLong reservedMemory = new AtomicLong();
private static final AtomicLong totalCapacity = new AtomicLong();
private static final AtomicLong count = new AtomicLong();
    
    
Bits.reserveMemory
堆外内存不够时 主动执行 System.gc()

unsafe.allocateMemory  分配内存,返回内存地址,并清 0


Bits.reserveMemory(size, cap);     
long base = unsafe.allocateMemory(size);
unsafe.setMemory(base, size, (byte) 0);

cleaner = Clearner.create(this , new Deallocator(base , size , cap)); 

public class sun.misc.Cleaner extends java.lang.ref.PhantomReference


堆外内存自动回收机制

Cleaner与GC关联

PhantomReference 不会影响GC

GC 添加到 Reference pending list里。
ReferenceHandler线程 处理 pending list, 对于Cleaner 对象 执行clean()
最终调用Unsafe的free接口释放堆外内存

Reference 类内部 static 块启动 ReferenceHandler 线程


手动回收

手动调用 DirectByteBuffer  cleaner 的 clean 方法

获取cleaner的两种方式
反射获取  
调用 DirectBuffer 的 cleaner 方法

public static void clean(final ByteBufferbyteBuffer) {  
    if(byteBuffer.isDirect()) { 
        Field cleanerField = byteBuffer.getClass().getDeclaredField("cleaner");
        cleanerField.setAccessible(true);
        Cleaner cleaner = (Cleaner) cleanerField.get(byteBuffer);
        cleaner.clean();
    }
}


public static void clean(final ByteBufferbyteBuffer) {    
    if(byteBuffer.isDirect()) {  
        ((DirectBuffer)byteBuffer).cleaner().clean();  
    }  
}


Netty使用反射手动回收

上一篇     下一篇
docker常用命令

docker Busybox 实战

java调用c方法JNA实例

ConcurrentHashMap在jdk7和8中的区别

优秀投资者的十大特征

springboot web端口设置三种方式