在将 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'");
}
不幸的是,出于架构原因,这对我的应用程序来说并不容易。我可能必须将单独的 ScriptEngine 实例放在 ThreadLocal 中。不过,不明白为什么这会失败让我担心。
关于为什么我会收到此“NameError:未初始化常量”错误的任何想法?不,我还没有尝试检查源...