プログラムにjavaeditorを追加して、実行時にプログラムを拡張しようとしています。プログラムを広範囲に使用する場合を除いて、すべて正常に動作します(1000〜10000のコンパイラ実行をシミュレートしました)。メモリ使用量がどんどん増えていき、メモリリークが発生しているようです。
私のプログラムでは、クラスがロードされ、コンストラクターが実行され、クラスがアンロードされます(ポインターをnullに設定すると、残りのインスタンスがなくなり、classLoaderが無効になります)。JConsoleを使用してプロセスを分析したところ、ガベージコレクターが実行されるとクラスがアンロードされます。
ヒープをメモリアナライザーで開きましたが、問題は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();
}
}