我試圖在運行時動態加載JRuby(所以我可以使用任意JRuby安裝和版本執行Ruby代碼)。我的計劃大致是創建一個可以訪問jruby.jar
的ClassLoader,然後使用它加載必要的JRuby運行時等。一切都很好,直到我需要多次執行此操作。如果我摧毀了第一個JRuby運行時,第三或第四個將導致OutOfMemory:PermGen空間。在運行時加載JRuby和ClassLoader泄漏
我已經減少了這個例子。該示例使用「直接」API以及JRuby Embed API。 「直接」API部分已被註釋掉,但都表現出相同的行爲:經過幾次迭代後,PermGen內存不足。 (使用JRuby 1.6.7和JRuby 1.6.5.1測試)
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.Test;
public class JRubyInstantiationTeardownTest {
@Test
public void test() throws Exception {
for (int i = 0; i < 100; ++i) {
URL[] urls = new URL[] {
new URL("file://path/to/jruby-1.6.7.jar")
};
ClassLoader cl = new URLClassLoader(urls, this.getClass().getClassLoader());
// "Direct" API
/*
Class<?> klass = cl.loadClass("org.jruby.Ruby");
Method newInstance = klass.getMethod("newInstance");
Method evalScriptlet = klass.getMethod("evalScriptlet", String.class);
Method tearDown = klass.getMethod("tearDown");
Object runtime = newInstance.invoke(null);
System.out.println("have " + runtime);
evalScriptlet.invoke(runtime, "puts 'hello, world'");
tearDown.invoke(runtime);
*/
// JRuby Embed API
Class<?> scriptingContainerClass = cl.loadClass("org.jruby.embed.ScriptingContainer");
Method terminate = scriptingContainerClass.getMethod("terminate");
Method runScriptlet = scriptingContainerClass.getMethod("runScriptlet", String.class);
Object container = scriptingContainerClass.newInstance();
System.out.println("have " + container);
runScriptlet.invoke(container, "puts 'hello, world'");
terminate.invoke(container);
}
}
}
的問題:這是試圖用一個ClassLoader做合理的事情?如果是這樣,這是JRuby中的錯誤,還是我在加載類時出錯?
獎勵:如果這是JRuby中的錯誤,Eclipse內存分析工具如何幫助查找源代碼?我可以打開一個堆轉儲並查看幾個Ruby對象(在任何給定時間,我預計不會超過一個),但我不知道如何找到爲什麼這些不會被垃圾收集...
您應該添加指向JRuby錯誤報告的鏈接作爲答案並接受它,因爲這看起來確實是JRuby錯誤。 – 2012-03-04 09:29:47