1. 程式人生 > >Java動態編譯優化——ZipFileIndex記憶體洩漏問題分析解決

Java動態編譯優化——ZipFileIndex記憶體洩漏問題分析解決

一、前言:

前幾天解決了URLClassLoader記憶體洩漏的問題,但是解決問題就像剝洋蔥,剝去了外層,內層 問題又暴露出來了。當URLClassLoader記憶體洩漏解決, 需要解決的就是ZipFileIndex記憶體洩漏的問題了,而且這個問題折騰了我2天半的時間。

URLClassLoader問題解決:https://blog.csdn.net/moneyshi/article/details/81939477

 

二、ZipFileIndex問題發現

在執行動態編譯的時候,用VisualVM分析堆Dump,發現com.sun.tools.javac.file.ZipFileIndex$Entry

類和例項記憶體佔比特別高,僅居String之後,具體如下圖:

查詢資料,ZipFileIndex 是JavacFileManager裡面用到的一個處理檔案的類,在jdk1.7之後加入進來的,jdk1.9裡面被刪除了。

 

三、解決方案

1、設定useJavaUtilZip

為了解決ZipFileIndex記憶體洩漏的問題,查閱大量資料,其中有個解決方案就是編譯時設定useJavaUtilZip=true,具體程式碼如下:

            System.setProperty("useJavaUtilZip", "true");
            //使用編譯選項可以改變預設編譯行為。編譯選項是一個元素為String型別的Iterable集合
            List<String> options = new ArrayList<>();
            options.add("-encoding");
            options.add("UTF-8");
            options.add("-classpath");
//            //獲取系統構建路徑
            options.add(buildClassPath());
            //不使用SharedNameTable (jdk1.7自帶的軟引用,會影響GC的回收,jdk1.9已經解決)
            options.add("-XDuseUnsharedTable");
            options.add("-XDuseJavaUtilZip");

            JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, jfiles);

參考資料:參考      ,參考2

但是實際上並沒什麼效果。ZipFileIndex記憶體佔比依然很高(不知道我是哪設定有問題)

 

2、升級JDK版本,由Java8升級到Java9 

花了兩天時間,都沒找到什麼好的解決方案,於是我想到去Oracle/Java 的Bug列表去找我想要的答案,終於讓我找到了資料,說明了JDK升級到9之後,會刪除ZipFileIndex相關的類,加入java.nio.file來處理檔案編譯,具體如下:

 

 

Oracle/Java的bug列表:

https://www.oracle.com/search/results?Ntt=&Dy=1&Nty=1&cat=bugs&Ntk=S3

參考文獻:

https://bugs.java.com/view_bug.do?bug_id=8039262

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8061702

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8059976

 

升級Java 9 版本後,動態編譯 ZipFileIndex不在出現。 問題完美解決。

 

後續可能更新String 、 LinkedList 、 HashMap的記憶體洩漏問題解決方案。