Rhino中的类型错误:从Java 6迁移到Java 7。

时间:2021-09-27 21:06:58

My project perfectly works on Java 6 (different updates and OS). It uses Rhino as script engine. Now we need to migrate to Java 7 and I found one issue that prevent us to do it. We have code like this:

我的项目非常适合于Java 6(不同的更新和操作系统)。它使用Rhino作为脚本引擎。现在我们需要迁移到Java 7,我发现了一个阻止我们去做的问题。我们有这样的代码:

Context.enter();
try {
    ScriptEngine js = new ScriptEngineManager().getEngineByName("js");
    final ScriptContext context = new SimpleScriptContext();
    context.setAttribute("console", new Object() {
        public void log(String out) {
            logger.info(out);
        }
    }, ScriptContext.ENGINE_SCOPE);
    js.setContext(context);
    js.eval("console.log('test')");
} catch (ScriptException e) {
    logger.error(e);
    e.printStackTrace();
} finally {
    Context.exit();
}

It works good in Java 6 but Java 7 throws exception

它在Java 6中运行良好,但Java 7抛出异常。

javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: TypeError: Cannot find function log in object JSDebugTest$1@4631f1f8. (<Unknown source>#1) in <Unknown source> at line number 1
at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:224)
at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:240)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
at JSDebugTest.testJS1(JSDebugTest.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at  com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: sun.org.mozilla.javascript.internal.EcmaError: TypeError: Cannot find function log in object JSDebugTest$1@4631f1f8. (<Unknown source>#1)
at sun.org.mozilla.javascript.internal.ScriptRuntime.constructError(ScriptRuntime.java:3771)
at sun.org.mozilla.javascript.internal.ScriptRuntime.constructError(ScriptRuntime.java:3749)
at sun.org.mozilla.javascript.internal.ScriptRuntime.typeError(ScriptRuntime.java:3777)
at sun.org.mozilla.javascript.internal.ScriptRuntime.typeError2(ScriptRuntime.java:3796)
at sun.org.mozilla.javascript.internal.ScriptRuntime.notFunctionError(ScriptRuntime.java:3867)
at sun.org.mozilla.javascript.internal.ScriptRuntime.getPropFunctionAndThisHelper(ScriptRuntime.java:2343)
at sun.org.mozilla.javascript.internal.ScriptRuntime.getPropFunctionAndThis(ScriptRuntime.java:2310)
at sun.org.mozilla.javascript.internal.gen._Unknown_source__2._c_script_0(<Unknown source>:1)
at sun.org.mozilla.javascript.internal.gen._Unknown_source__2.call(<Unknown source>)
at sun.org.mozilla.javascript.internal.ContextFactory.doTopCall(ContextFactory.java:433)
at sun.org.mozilla.javascript.internal.ScriptRuntime.doTopCall(ScriptRuntime.java:3161)
at sun.org.mozilla.javascript.internal.gen._Unknown_source__2.call(<Unknown source>)
at sun.org.mozilla.javascript.internal.gen._Unknown_source__2.exec(<Unknown source>)
at sun.org.mozilla.javascript.internal.Context.evaluateReader(Context.java:1159)
at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:214)
... 30 more

Problem disappear if I extract anonymous Object to inner class. Any idea how to fix it without ScriptableObject.get (there are too many places where we create such object and some third party code we use, uses same approach)?

如果我将匿名对象提取到内部类,问题就消失了。知道如何在没有脚本对象的情况下修复它。get(我们创建这样的对象和我们使用的第三方代码的地方太多了,使用相同的方法)?

4 个解决方案

#1


1  

I had exactly the same error, and after your comment "Problem disappear if I extract anonymous Object to inner class." I found that generated inner class will have default access modifier (sometimes called 'package' access modifier). Apparently, scripting API in JDK7 doesn't handle these definitions!

我有完全相同的错误,在您的评论“问题消失了,如果我提取匿名对象到内部类。”我发现生成的内部类将有默认的访问修饰符(有时称为“包”访问修饰符)。显然,JDK7中的脚本API不处理这些定义!

I use put a "static public" definition instead.

我使用的是“静态公共”定义。

#2


0  

Had a similar problem. I was passing in a private inner class and it was failing. I changed it from a private inner object to a public class and it worked just fine after the Java 7 upgrade.

有一个类似的问题。我正在通过一个私人的内部课程,但它失败了。我将它从一个私有的内部对象更改为一个公共类,在Java 7升级之后它运行良好。

#3


0  

I also got TypeError when migrating from Java 6 to 7: my JavaScript was calling a method on a Java class which had default (package-private) visibility. Had to make the class public for it to work.

在从Java 6迁移到7时,我也遇到了类型错误:我的JavaScript调用了一个Java类的方法,它有默认的(package-private)可见性。必须让班上的同学都能工作。

#4


0  

Had the same problem. In my case it was not an inner class, but the top level class had a default (package level) protection. Switching to public fixed my issues ... shame it took me a couple hours to figure it out.

有同样的问题。在我的例子中,它不是一个内部类,但是顶层类有一个默认的(包级)保护。切换到公众解决我的问题…真遗憾我花了几个小时才弄明白。

#1


1  

I had exactly the same error, and after your comment "Problem disappear if I extract anonymous Object to inner class." I found that generated inner class will have default access modifier (sometimes called 'package' access modifier). Apparently, scripting API in JDK7 doesn't handle these definitions!

我有完全相同的错误,在您的评论“问题消失了,如果我提取匿名对象到内部类。”我发现生成的内部类将有默认的访问修饰符(有时称为“包”访问修饰符)。显然,JDK7中的脚本API不处理这些定义!

I use put a "static public" definition instead.

我使用的是“静态公共”定义。

#2


0  

Had a similar problem. I was passing in a private inner class and it was failing. I changed it from a private inner object to a public class and it worked just fine after the Java 7 upgrade.

有一个类似的问题。我正在通过一个私人的内部课程,但它失败了。我将它从一个私有的内部对象更改为一个公共类,在Java 7升级之后它运行良好。

#3


0  

I also got TypeError when migrating from Java 6 to 7: my JavaScript was calling a method on a Java class which had default (package-private) visibility. Had to make the class public for it to work.

在从Java 6迁移到7时,我也遇到了类型错误:我的JavaScript调用了一个Java类的方法,它有默认的(package-private)可见性。必须让班上的同学都能工作。

#4


0  

Had the same problem. In my case it was not an inner class, but the top level class had a default (package level) protection. Switching to public fixed my issues ... shame it took me a couple hours to figure it out.

有同样的问题。在我的例子中,它不是一个内部类,但是顶层类有一个默认的(包级)保护。切换到公众解决我的问题…真遗憾我花了几个小时才弄明白。