JAVA NIO内存泄漏

前言

写NIO程序时,常用ByteBuffer来读取写入数据,那使用ByteBuffer.allocate()仍是ByteBuffer.allocateDirect分配呢?java

  • allocate()分配的是jvm堆内存,属于GC管理范畴,须要堆内拷贝,速度较慢。
  • allocateDireact()直接分配堆外内存,属于OS范畴,没有GC管理,速度较快。

咱们但愿使用速度更快的方式,可是没有GC管理会产生OOM的问题。react

好在OS内存在java中有个DirectByteBuffer与之对应,当GC发生时,这个类会被回收,对应的OS内存会被回收,这样就知足了咱们的想法。 可是若是堆内一直够用,不触发GC,DirectByteBuffer不进行GC呢?对应的OS内存也不会回收。缓存

既然自动GC方式不靠谱,好在DirectByteBuffer里面有个Cleaner对象,里面有个clean()方法,经过这个方法咱们能够经过手动方式释放了。jvm

测试

  1. 分配-Xmx=100m,没有设置-XX:MaxDirectMemorySize,默认大小和-Xmx大小相同测试

    //分配128MB直接内存 ByteBuffer bb = ByteBuffer.allocateDirect(10241024128);code

产生OOM;对象

  1. 设置JVM参数-Xmx256m -XX:MaxDirectMemorySize=100M

一样的代码产生OOM;内存

  1. 手动释放

public static void main(String[] args) throws InterruptedException{ //分配512MB直接缓存 ByteBuffer bb = ByteBuffer.allocateDirect(10241024512);it

TimeUnit.SECONDS.sleep(10);
     
    //清除直接缓存
    ((DirectBuffer)bb).cleaner().clean();
     
    TimeUnit.SECONDS.sleep(10);
     
    System.out.println("ok");
}

以后经过观察内存使用变化,发现从以前一直升高,到调用clean()以后,内存降下来,说明clean()方法生效了。io

相关文章
相关标签/搜索