2012-11-26 75 views
1

我需要在運行時從jar文件中讀取Manifest文件。來自java.util.zip.Inflater.init的奇怪java.lang.OutOfMemoryError(Native Method)

代碼:

JarFile someJar = new JarFile(jarFile); 
manifest = someJar.getManifest(); 

然而,有時上面的代碼中拋出的OutOfMemoryError異常:

java.lang.OutOfMemoryError 
    at java.util.zip.Inflater.init(Native Method) 
    at java.util.zip.Inflater.<init>(Inflater.java:83) 
    at java.util.zip.ZipFile.getInflater(ZipFile.java:278) 
    at java.util.zip.ZipFile.getInputStream(ZipFile.java:224) 
    at java.util.zip.ZipFile.getInputStream(ZipFile.java:192) 
    at java.util.jar.JarFile.getBytes(JarFile.java:361) 

有時能告訴我如何避免這種情況的例外(也許另一種方式來獲得清單在運行時)?

btw,我沒有權限更改java堆大小。

+0

也許你的其他代碼導致內存泄漏? –

+0

嘗試在執行此代碼之前監視空閒/佔用的內存量 –

+0

即使無法保證,也可以嘗試調用System.gc() –

回答

0

這是不是一個腐敗的jar文件,混淆了Inflater認爲它需要分配大量的內存?

如果是這樣,您可能會發現實際上可以捕獲OutOfMemoryError。 (您通常不能或不應該捕獲這些內容,但在試圖分配大量內存的特定情況下,實際上這樣做通常是安全的。)

+0

不,該jar沒有損壞。 –

0

This可能與您運行的ZIP文件無關。

查看JDK 1.7代碼,Inflater構造函數最終調用名爲init的本地方法,併爲其提供一個布爾參數。沒有跡象表明任何對ZIP文件的引用。

看起來好像你使用的是JRE中的一個錯誤,或者你的系統在堆內存中極其有限(包含大多數ZIP功能的本地ZIP庫非常小)。

您的JRE在OutOfMemoryError時發出堆轉儲嗎?如果是這樣,你可能想看看那裏。

0

這似乎是一個關於java.util.zip.Inflater的已知問題。

Inflater會在初始化期間從堆內存中分配,如果在路由後沒有調用end(),內存將一直存在,直到GC調用完成函數。它堆很大,finalize()在使用所有內存之前不會調用。

請參考此問題:excessive memory use by java,
或此JDK錯誤報告:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4797189

我通過下面的代碼驗證它,直到JDK8,它仍然存在。

public static void main(String args[]) throws InterruptedException { 
    while (true) { 
     //final Deflater deflater = new Deflater(9, true); 
     final Inflater inflater = new Inflater(true); 
     // .... 
     // if not call end() after using inflater, it will OOM 
     // inflater.end(); 
     Thread.sleep(10); 
    } 
} 

解決方法如此簡單,只需在完成使用充氣器後調用end()*即可。

相關問題