写NIO程序时,经常使用ByteBuffer来读取写入数据,那使用ByteBuffer.allocate()还是ByteBuffer.allocateDirect分配呢?
我们希望使用速度更快的方式,但是没有GC管理会产生OOM的问题。
好在OS内存在java中有个DirectByteBuffer与之对应,当GC发生时,这个类会被回收,对应的OS内存会被回收,这样就满足了我们的想法。 但是如果堆内一直够用,不触发GC,DirectByteBuffer不进行GC呢?对应的OS内存也不会回收。
既然自动GC方式不靠谱,好在DirectByteBuffer里面有个Cleaner对象,里面有个clean()方法,通过这个方法我们可以通过手动方式释放了。
产生OOM;
同样的代码产生OOM;
public static void main(String[] args) throws InterruptedException{ //分配512MB直接缓存 ByteBuffer bb = ByteBuffer.allocateDirect(10241024512);
TimeUnit.SECONDS.sleep(10);
//清除直接缓存
((DirectBuffer)bb).cleaner().clean();
TimeUnit.SECONDS.sleep(10);
System.out.println("ok");
}
之后通过观察内存使用变化,发现从之前一直升高,到调用clean()之后,内存降下来,说明clean()方法生效了。