将JRuby从1.5.2升级到1.6.1时遇到了一个有趣的问题。整个周末都在悄悄走出来,直到我把它煮成一些线条。似乎在某个地方引入了一个错误,当getEngineByName被调用太多次时会导致失败。例如,以下超简单代码在1.5.2中工作,但在大约10-20次迭代后在1.6.1中失败:
ScriptEngineManager factory = new ScriptEngineManager();
for (int i = 0; i < 10000; i++) {
System.out.println(i);
ScriptEngine engine = factory.getEngineByName("jruby");
engine.eval("puts 'hello'");
}
#16之后的1.6.1结果:
NameError: uninitialized constant #<Class:0x101a41cc7>::ARGV
const_missing at org/jruby/RubyModule.java:2526
Exception in thread "main" java.lang.NullPointerException
at org.jruby.embed.jsr223.JRubyEngine.wrapException(JRubyEngine.java:110)
at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:93)
at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:154)
at JRubyTestFailure.main(JRubyTestFailure.java:16)
为了避免这个问题,您需要做的就是将getEngineByName移到循环之外:
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("jruby");
for (int i = 0; i < 10000; i++) {
System.out.println(i);
engine.eval("puts 'hello'");
}
不幸的是,出于架构原因,这对我的应用程序来说并不那么容易。我可能必须在ThreadLocal中放置单独的ScriptEngine实例。不明白为什么这会失败让我担心。
有关为什么我收到此“NameError:uninitialized constant”错误的任何想法?不,我还没有尝试检查来源......