java bytebuffer回收_Java中的DirectByteBuffer是如何被回收的

在SunJDK中,java.nio.DirectByteBuffer是由ByteBuffer#allocateDirect(int)创建的,它有一个类型为sun.misc.Cleaner的字段,Cleaner继承了java.lang.ref.PhantomReference(虚引用).

DirectByteBuffer创建时cleaner字段赋值,传入一个Runnable类型的Deallocator对象(用于释放内存)

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

当Cleaner被收集并且即将移入关联的引用队列时,GC收集相关的线程通过ReferenceHandler对Cleaner类型的Reference实例特殊处理:将引用实例向下转型为Cleaner,然后调用Cleaner#clean(),最终会回到调用DirectByteBuffer$Deallocator#run(),进而调用Unsafe#freeMemory(long).

可以看到,并没有对Object#finalize()的调用.

总之,如果释放对DirectByteBuffer实例的引用,一般就不会耗尽内存,只要垃圾收集器有机会注意到这种情况,之后它的引用处理线程就会执行上述过程.

Cleaner对象

虚引用的子类型.对象构造时传入一个Runnable用于在引用处理线程执行时调用.

Reference.java 注意本代码的第55行

private static class ReferenceHandler extends Thread {

private static void ensureClassInitialized(Class> clazz) {

try {

Class.forName(clazz.getName(), true, clazz.getClassLoader());

} catch (ClassNotFoundException e) {

throw (Error) new NoClassDefFoundError(e.getMessage()).initCause(e);

}

}

static {

// pre-load and initialize InterruptedException and Cleaner classes

// so that we don‘t get into trouble later in the run loop if there‘s

// memory shortage while loading/initializing them lazily.

ensureClassInitialized(InterruptedException.class);

ensureClassInitialized(Cleaner.class);

}

ReferenceHandler(ThreadGroup g, String name) {

super(g, name);

}

public void run() {

while (true) {

tryHandlePending(true);

}

}

}

/**

* Try handle pending [email protected] Reference} if there is one.

* Return [email protected] true} as a hint that there might be another

* [email protected] Reference} pending or [email protected] false} when there are no more pending

* [email protected] Reference}s at the moment and the program can do some other

* useful work instead of looping.

*

* @param waitForNotify if [email protected] true} and there was no pending

* [email protected] Reference}, wait until notified from VM

* or interrupted; if [email protected] false}, return immediately

* when there is no pending [email protected] Reference}.

* @return [email protected] true} if there was a [email protected] Reference} pending and it

* was processed, or we waited for notification and either got it

* or thread was interrupted before being notified;

* [email protected] false} otherwise.

*/

static boolean tryHandlePending(boolean waitForNotify) {

Reference r;

Cleaner c;

try {

synchronized (lock) {

if (pending != null) {

r = pending;

// ‘instanceof‘ might throw OutOfMemoryError sometimes

// so do this before un-linking ‘r‘ from the ‘pending‘ chain...

c = r instanceof Cleaner ? (Cleaner) r : null;

// unlink ‘r‘ from ‘pending‘ chain

pending = r.discovered;

r.discovered = null;

} else {

// The waiting on the lock may cause an OutOfMemoryError

// because it may try to allocate exception objects.

if (waitForNotify) {

lock.wait();

}

// retry if waited

return waitForNotify;

}

}

} catch (OutOfMemoryError x) {

// Give other threads CPU time so they hopefully drop some live references

// and GC reclaims some space.

// Also prevent CPU intensive spinning in case ‘r instanceof Cleaner‘ above

// persistently throws OOME for some time...

Thread.yield();

// retry

return true;

} catch (InterruptedException x) {

// retry

return true;

}

// Fast path for cleaners

if (c != null) {

c.clean();

return true;

}

ReferenceQueue super Object> q = r.queue;

if (q != ReferenceQueue.NULL) q.enqueue(r);

return true;

}

原文:https://www.cnblogs.com/onion94/p/Java-DirectByteBuffer-How-Release.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值