在 Java 中调用 ImportClass 6

Invoking ImportClass in Java 6

我正在做一个项目,该项目需要从一段 Java 脚本中调用 Java class,该脚本由另一段 Java 执行代码。它最初在 Java 7.51 中工作,但它也需要在 Java 1.6 中工作。0_27 但失败并显示 function importclass must be called with a class 错误消息。

这两个 JAR 是使用 Export > JAR 命令通过 Eclipse Indigo 生成的。

我创建了一个简单的 MCVE,如下所示来演示该问题。使用以下命令行执行的堆栈跟踪...

java -cp Sanity.jar;SanityCheck.jar -jar SanityCheck.jar

...如下:

    javax.script.ScriptException: sun.org.mozilla.javascript.internal.EvaluatorException: Function importClass must be called with a class; had "[JavaPackage com.sanity.Sanity]" instead. (<Unknown source>#1) in <Unknown source> at line number 1
        at com.sun.script.javascript.RhinoScriptEngine.eval(Unknown Source)
        at com.sun.script.javascript.RhinoScriptEngine.eval(Unknown Source)
        at javax.script.AbstractScriptEngine.eval(Unknown Source)
        at com.sanity.SanityCheck.<init>(SanityCheck.java:22)
        at com.sanity.SanityCheck.main(SanityCheck.java:52)
    Exception in thread "main" java.lang.NullPointerException
        at com.sanity.SanityCheck.invoke(SanityCheck.java:31)
        at com.sanity.SanityCheck.main(SanityCheck.java:53)

谁能看出我哪里出错了?

Sanity.java(在自己的同名 JAR 中)

    package com.sanity;

    public class Sanity {

        public Sanity() {}

        public void doCheck() {
            System.out.println("Sanity Check Passed!");
        }

    }

SanityCheck.java(在自己的同名 JAR 中)

    package com.sanity;

    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;

    import javax.script.Invocable;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;

    public class SanityCheck {

        private Invocable invoker;

        public SanityCheck(String script) {
            try {
                ScriptEngineManager manager = new ScriptEngineManager();
                ScriptEngine engine = manager.getEngineByName("JavaScript");

                engine.eval(script);
                invoker = (Invocable) engine;
            } catch (ScriptException e) {
                e.printStackTrace();
            }
        }

        public void invoke() {
            try {
                invoker.invokeFunction("run");
            } catch (ScriptException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }

        public static void main(String[] args) {
            StringBuilder builder = new StringBuilder();

            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("Sanity.js")));
                String line = null;

                while ((line = reader.readLine()) != null) {
                    builder.append(line);
                }

                reader.close();

                SanityCheck check = new SanityCheck(builder.toString());
                check.invoke();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Sanity.js

    importClass(Packages.com.sanity.Sanity);

    function run() {
            var sanObj = new Sanity();
            sanObj.doCheck();
    }

好消息:问题与您的 Java 或 Java 脚本代码无关。它与命令的效果有关:

java -cp [...] -jar <jar-file>

执行该命令时,忽略 -cp 参数,<jar-file> 用作 整个 类路径。

-jar 选项的 Java 6 documentationjava 工具:

When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.

所以你的命令的一个版本是:

java -cp Sanity.jar;SanityCheck.jar com.sanity.SanityCheck

我使用以下目录结构复制了您的示例,没有修改您的代码:

Sanity.js
com/
    sanity/
        Sanity.java
        SanityCheck.java

... 然后 运行 从顶级目录执行以下命令:

$ /usr/lib/jvm/java-1.6.0-openjdk-amd64/bin/javac com/sanity/*.java && /usr/lib/jvm/java-1.6.0-openjdk-amd64/bin/java -classpath . com.sanity.SanityCheck

...并得到了

Sanity Check Passed!

错误归因于从 Java 脚本调用的 JAR 文件是针对 Java 7 而不是 Java 6 编译的。尝试 运行 Eclipse 中的一个主要方法很快揭示了这一点。

快速重新编译 JAR 文件,现在可以使用了。