Java动态编译优化——ZipFileIndex内存泄漏问题分析解决

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shijing266/article/details/82019580

一、前言:

前几天解决了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的内存泄漏问题解决方案。

猜你喜欢

转载自blog.csdn.net/shijing266/article/details/82019580
今日推荐