首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ScriptEngine重用参数?

ScriptEngine重用参数?
EN

Stack Overflow用户
提问于 2022-06-28 17:10:27
回答 1查看 56关注 0票数 0

我在ScriptEngine的KotlinsJSR-223实现中遇到了一些奇怪的问题(kotlin-scripting JSR 223)

基本上,我有一个条件,我解析并编译成一个CompiledScript:

代码语言:javascript
复制
fun parse(clazz: KClass<out GenericEvent>, condition: String): String {
    val simpleName = clazz.simpleName
    return """
        import ${clazz.java.name}
        
        val condition: $simpleName.() -> Boolean = { ${trimQuotes(condition)} }
        
        fun check(event: $simpleName) = condition.invoke(event)
            
    """.trimIndent()
}

然后使用(engine as Compilable).compile(code)将结果字符串编译成一个CompiledScript

现在,每当我尝试在很短的时间内多次eval()这些CompiledScript

代码语言:javascript
复制
listener.compiledScript.eval()
return@Callable (engine as Invocable).invokeFunction("check", event)

它似乎重用了以前使用过的参数。首先,我认为这是一个线程安全问题(因为它看上去很像),但是使用Mutex或单个线程执行程序编译脚本并没有改变这种行为。

完整代码:

代码语言:javascript
复制
override suspend fun onEvent(e: GenericEvent) {
    val events = listeners[e.javaClass] ?: return

    events.forEach { listener ->
        try {
            val event = e.javaClass.cast(e)
            if (listener.compiledScript != null) {
                val result = executor.submit(Callable { // executor = Executors.newSingleThreadExecutor()
                    println(Thread.currentThread().id) // confirms it's always the same thread
                    listener.compiledScript.eval()
                    return@Callable (engine as Invocable).invokeFunction("check", event)
                }).get()
                if (result is Boolean && result)
                    listener.method.callSuspend(listener.instance, event)
            } else {
                listener.method.callSuspend(listener.instance, event)
            }
        } catch (throwable: Throwable) {
            log.error("An error occurred while evaluating listener condition!", throwable)
        }
    }
}

一开始,这是按预期工作的。

代码语言:javascript
复制
Condition: message.contentRaw == "first"
Is actually: first

但它创造了奇怪的,但总是相同的模式之后。

代码语言:javascript
复制
Condition: message.contentRaw == "first"
Is actually: second

Condition: message.contentRaw == "second"
Is actually: second

Condition: message.contentRaw == "first"
Is actually: second

Condition: message.contentRaw == "second"
Is actually: second

Condition: message.contentRaw == "first"
Is actually: second

Condition: message.contentRaw == "second"
Is actually: second

(如果条件不为真,则不应打印这些消息)

我在前面做了一些调试,在其中我在编译代码本身中打印了条件和实际事件,并且它在check()中重用了前面的事件参数,尽管我实际上在其中使用了一个完全不同的事件参数。

EN

回答 1

Stack Overflow用户

发布于 2022-06-28 19:51:20

通过创建一个新的SimpleScriptContext,将其传递到CompiledScripteval()方法,然后在调用invokeFunction()之前用新创建的上下文调用ScriptEngine#setContext来修正这个问题。

疯狂的东西!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72790632

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档