我正在尝试将 javaeditor 添加到我的程序中以在运行时扩展程序。一切正常,除非广泛使用该程序(我模拟了 1000-10000 次编译器执行)。内存使用率越来越高,看起来好像有内存泄漏。
在我的程序中,类被加载,构造函数被执行并且类被卸载(没有剩余的实例并且类加载器变得无效,因为我将指针设置为空)。我用 JConsole 分析了这个过程,当垃圾收集器被执行时,这些类被卸载了。
我做了一个 heapdum 在内存分析器中打开它,问题似乎出在 java.net.FactoryURLClassLoader 内部(在 com.sun.tools.javac.util.List 对象中)。由于 (com.sun.tools.javac) 是 JDK 的一部分,而不是 JRE 的一部分,并且 SystemToolClassLoader 是一个 FactoryURLClassLoader 对象,因此我会在某处找到泄漏。当我第一次执行编译器时,SystemToolClassLoader 中加载的类数从 1 增加到 521,但之后保持不变。
所以我不知道泄漏在哪里,有没有办法重置 SystemToolClassLoader?我怎样才能更准确地定位泄漏。
编辑:好的,我发现它也出现在一个非常简单的例子中。所以它似乎是编译的一部分,我不需要加载类或实例化它:
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class Example {
public static void main(String[] args)
{
for (int i =0; i<10000;i++){
try {
System.out.println(i);
compile();
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void compile() throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException
{
File source = new File( "src\\Example.java" ); // This File
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null );
Iterable<? extends JavaFileObject> units;
units = fileManager.getJavaFileObjectsFromFiles( Arrays.asList( source ) );
compiler.getTask( null, fileManager, null, null, null, units ).call();
fileManager.close();
}
}