当前位置: 首页 > 知识库问答 >
问题:

jdk10java中的Nashorn。type()奇怪的行为

郤旭东
2023-03-14

大家好,
我正在编写一个应用程序,根据旧电脑中存储的信息进行计算。dbf文件来自旧的fox pro for MS-DOS系统,这些计算生成日记账分录,用于新的簿记-ERP系统;用户应该能够动态添加/删除/修改条目的生成。因此,我的解决方案是使用Nashorn脚本引擎:我在应用程序设置中定义了一个文件夹,然后应用程序扫描所有文件。这个文件夹中的js文件扩展了一个生成条目的抽象类(累加器),瞧
所有听起来都不错,只是它不起作用B-
累加器抽象类的源代码是:

public abstract class Totalizer {

    private List<Expense> expenses;
    private List<Employee> distribution;

    /**
     * 
     * @return Id of the totalizer.
     */
    public abstract String getId();

    /**
     * @return Descriptive title of the totalizer.
     */
    public abstract String getTitle();

    /**
     * Creates the JournalEntry based upon a single DBF record.
     *
     * @param record dbf record.
     * @return List of journal entries.
     * @throws java.lang.Exception if any exception is thrown.
     */
    public abstract List<JournalEntry> totalize(
            DbfRecord record) throws Exception;

    public void setExpenseMapping(List<Expense> expenses) {
        this.expenses = expenses;
    }

    public void setDistribution(List<Employee> distribution) {
        this.distribution = distribution;
    }

}

然后,我有脚本文件,我共享其中一个,因为它们都是相似的:

/**
* Vacations expenses entry:
*/
var BenefVacaciones = Java.extend(Totalizer, {
    getId : function(){
        return "diar.BenefVaca";
    },
    getTitle : function(){
        return "Beneficios: Vacaciones.";
    },

    totalize : function(record){
        //TODO: implement this method.
        return null;
    }
});

/*
* Creates a new instance of BenefVacaciones.
*/
function createInstance() {
    return new BenefVacaciones();
}

然后,“加载”脚本的类是任务的实现,它执行以下操作:

//Loads a script and returns totalizer implementation.
public Totalizer loadScript(File aFile) throws IOException, ScriptException{
    //creates the engine.
    var engine = new NashornScriptEngineFactory().getScriptEngine();
    //reads script from FileReader
    try(var reader = new FileReader(aFile)){
        var obj = engine.eval(reader);
        if(obj instanceof Invocable){//if obj is invocable
            var inv = (Invocable)obj;//casts to invocable
            var ret = inv.invokeFunction("createInstance");//invoke
            if(ret instanceof Totalizer){//if invoked function is Totalizer
                return (Totalizer)ret;//return that totalizer
            }else if(ret == null){//if invoked function returns null
                throw new NullPointerException("return value is null.");
            }else{//if returns non-null value but isn't Totalizer
                throw new ScriptException("Function createInstance won't return Totalizer");
            }
        }else if(obj == null){//WATCH: If engine.eval returns null
            throw new NullPointerException("engine.eval returns null.");
        }else{//If engine.eval returns non-invocable value.
            throw new ScriptException("Cannot get invocable object.");
        }
    }
}

当然,这段代码应该抛出一个

ScriptException,ReferenceError中未定义“累加器”

但有趣的是,如果我在. js脚本文件中添加以下行:

var Totalizer = Java.type('com.fossc.diar.onfalo.jsapi.Totalizer');

然后,引擎。eval返回null,当我希望得到一个Invocable对象,或者至少是任何其他对象的实例时,代码执行落入带有注释“WATCH:If engine.eval returns null”的累加器行。没有抛出异常,因此我没有任何信息。我还尝试在引擎声明之后立即向loadScript方法添加以下行:

engine.put(
    "Totalizer",
    jdk.dynalink.beans.StaticClass.forClass(Totalizer.class));

但它返回null。还尝试添加一个总是返回true的类过滤器,但两者都不起作用。我一直在寻找解决方案,但似乎没有工作,当我使用Java.type()在任何脚本,engine.eval返回一个空对象,而不是一个Invocable实例,甚至测试engine.eval("var x=Java.type(\'java.lang.字符串\');") 返回null。
出于用户界面的原因,我从JavaFX任务实现中调用loadScript函数,所以我发现https://stackoverflow.com/questions/33945507/java-nashorn-classnotfoundexception-java-type并尝试设置当前hread.contextClassLoader到otalizer.class.getClassLoader()
我做错了什么吗?
我使用以下软件:

  • IDE:Apache Netbeans 9.0(构建孵化器-Netbeans-release-334-on-20180708)

共有1个答案

封昊天
2023-03-14

好吧,有点尴尬,但我发现了错误。

var obj = engine.eval(reader);

在这种情况下,总是返回null,如果我写了以下内容,它只返回一个值:

engine.eval("2+2");

错误在于引擎本身是可Invocable对象。所以,我只需要铸造引擎,而不是评估结果:

engine.eval(reader);
var inv = (Invocable)engine;
var ret = inv.invokeFunction("createInstance");
if(ret instanceof Totalizer){
    return (Totalizer) ret;
}else if(ret == null){
    throw new NullPointerException("createInstance returns null.");
}else{
    throw new ScriptException("createInstance dont return Totalizer.");
}

一切正常。当然,在这种情况下,如果我做引擎。没有引擎的评估。put或Java。类型,则会出现ReferenceError,因为脚本端不存在累加器,这表明我只需要“导入”该类。但是引擎。该脚本的eval应该始终返回null,因此当错误被修复时,它就是这样做的:返回null。

 类似资料:
  • 我有以下代码来解析一个JSON文件: 要处理以下JSON文件: 如果我执行此代码,我将收到以下错误: 所以我开始一步一步地调试应用程序,看看part processing()中的哪个代码部分抛出了这个异常。令人惊讶的是,那里的所有代码都正常执行:没有抛出异常,也没有返回结果I except。 更让我惊讶的是,当我稍微改变第一种方法的代码时,它可以在不产生异常的情况下工作。 我不知道println方

  • 我在http://www.nodebeginner.org上读了一篇教程,我在数据输出中有一个奇怪的行为。我知道,Stackoverflow也有类似的问题,但没有答案。所以我有这个Web-Server的代码: 调用RequestHandler.Upload的Router.js代码-我的buggy函数 和RequestHandler.Upload的代码 假设POST数据中有一个字符串。该函数的第一行

  • 我正在编写一个DocumentFilter,它将输入JTextField的所有单词“top”替换为逻辑top符号。 使用此代码很好,但是它很烦人,因为用户必须重新键入他们的空间,他们可以这样做,并且文本继续在同一行上 当用户继续键入文本时,使用此代码并在空格中添加替换符会导致顶部符号和JTextField中的所有文本稍微向上推,然后转到下面并开始一行新的内容 有人能解释一下这种行为,并希望能提供一

  • 我在做Maven项目。我用log4j做了一个日志。但它在给定的文件中显示了一些starnge日志。我试图理解,为什么会出现这种奇怪的日志,但我不明白。请帮助我,为什么这些不需要的行会进入日志文件。 请帮我把这个拿开。 log.properties 我通过阅读这个链接创建了这个文件。 代码是 日志txt-(log.txt的一些起始行)

  • 使用方式如下: 这是有效的解决方案吗?如果删除未使用的“魔术”变量 - 我在返回字符串后有分割错误。做错了什么? $gcc--version gcc(Debian 4.4.5-8)4.4.5 $uname-Linux深度站(挤压)2.6.32-5-686#1 SMP 5月10日星期五08:33:48 UTC 2013 i686 GNU/Linux

  • 问题内容: 我在GregorianCalendar类中遇到一个奇怪的行为,我想知道我是否真的做得不好。 仅当初始化日期的月份的实际Maximum大于我将日历设置为的月份时,才追加此值。 这是示例代码: 我知道问题是由于日历初始化日期是31天(可能是5月),与设置为2月(28天)的月份混淆了。修复很容易(只需在设置年和月之前将day_of_month设置为1),但是我想知道这确实是想要的行为。有什么