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

相關文章
相關標籤/搜索