java.util.zip.Deflater/Inflater 底層調用 JNI 分配堆外內存,若僅依賴 GC 回收 Java 對象而不顯式調用 end(),將導致 Native Memory Leak,表現為 Java 進程虛擬地址空間持續增長,GC 後不下降。
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 機制不可靠(延遲、不保證執行),不可依賴。