DirectByteBuffer内存释放,linux技术员

long base = 0;

try {

base = unsafe.allocateMemory(size); //分配直接内存,base表示的是直接内存的开始地址

} catch (OutOfMemoryError x) {

Bits.unreserveMemory(size, cap);

throw x;

}

unsafe.setMemory(base, size, (byte) 0);

if (pa && (base % ps != 0)) {

// Round up to page boundary

address = base + ps - (base & (ps - 1));

} else {

address = base;

}

cleaner = Cleaner.create(this, new Deallocator(base, size, cap));//注册钩子函数,释放直接内存

att = null;

}

}

可以看到构造方法中的确是用了unsafe.allocateMemory方法帮我们分配了直接内存,另外,在构造方法的最后,通过 Cleaner.create方法注册了一个钩子函数,用于清除直接内存的引用。

Cleaner.create方法声明如下所示:

public static Cleaner create(Object heapObj, Runnable task)

其中第一个参数是一个堆内存对象,第二个参数是一个Runnable任务,表示这个堆内存对象被回收的时候,需要执行的回调方法。我们可以看到在DirectByteBuffer的最后一行中,传入的这两个参数分别是this,和一个Deallocator(实现了Runnable接口),其中this表示就是当前DirectByteBuffer实例,也就是当前DirectByteBuffer被回收的时候,回调Deallocator的run方法

Deallocator就是用于清除DirectByteBuffer引用的直接内存,代码如下所示:

private static class Deallocator

implements Runnable

{

private static Unsafe unsafe = Unsafe.getUnsafe();

private long address;

private long size;

private int capacity;

private Deallocator(long address, long size, int capacity) {

assert (address != 0);

this.address = address;

this.size = size;

this.capacity = capacity;

}

public void run() {

if (address == 0) {

// Paranoia

return;

}

unsafe.freeMemory(address);//清除直接内存

address = 0;

Bits.unreserveMemory(size, capacity);

}

}

可以看到run方法中调用了unsafe.freeMemory方法释放了直接内存的引用。

System.gc

========================================================================

在DirectByteBuffer实例创建时,分配内存之前调用了Bits.reserveMemory,如果分配失败调用了Bits.unrese

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

浏览器打开:qq.cn.hn/FTf 免费领取

rveMemory,同时在Deallocator释放完直接内存的时候,也调用了Bits.unreserveMemory方法。

这两个方法,主要是记录jdk已经使用的直接内存的数量,当分配直接内存时,需要进行增加,当释放时,需要减少,源码如下:

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);//休眠100秒,等待垃圾回收完成

} catch (InterruptedException x) {

// Restore interrupt status

Thread.currentThread().interrupt();

}

synchronized (Bits.class) {//休眠100毫秒后,增加直接内存引用的计数

if (totalCapacity + cap > maxMemory)

throw new OutOfMemoryError(“Direct buffer memory”);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值