首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Deflater/Inflater 原生內存洩漏陷阱:必須調用 end() 釋放 Native 資源

     編輯:Java 相關知識

java.util.zip.Deflater/Inflater 底層調用 JNI 分配堆外內存,若僅依賴 GC 回收 Java 對象而不顯式調用 end(),將導致 Native Memory Leak,表現為 Java 進程虛擬地址空間持續增長,GC 後不下降。

複現代碼(-Xmn10m 運行觀察進程內存)

public class Bug {
    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                for (int j = 0; j < 200; j++) {
                    Deflater deflater = new Deflater(9, true);
                    // deflater.end(); // 註釋此行觸發洩漏
                }
                // 佔用堆內存促發 GC
                new byte[512*1024]; // ×8
            }).start();
            Thread.sleep(1);
        }
        Thread.sleep(30000);
    }
}

現象對比

  • 未調用 end():Minor/Full GC 後進程地址空間不降,持續增長
  • 調用 deflater.end():進程地址空間穩定,GC 有效回收

最佳實踐

將 Deflater/Inflater 視同 FileInputStream 等持有系統資源的對象:

  • 用完立即調用 end()
  • 配合 try-with-resources(Java 7+)或 finally 確保釋放
  • 避免在高頻循環中創建而不釋放

原理補充

Native 內存由 C 堆管理,不受 Java GC 直接控制。end() 釋放 JNI 層分配的 z_stream 結構體內存。Finalizer 機制不可靠(延遲、不保證執行),不可依賴。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved