解释时获取 Nashorn 脚本行号

Get Nashorn script line number during interpretation

我的代码使用 Nashorn 为用户提供脚本功能,许多 类 和在 Java 上实现的功能通过 Nashorn 暴露给脚本。

程序的任务之一当然是在遇到任何与脚本相关的错误时向用户报告。如果出现 ScriptException ,这非常简单,只需捕获异常并使用方法 getLineNumber() returns 正确的值即可。然而,偶尔会发生异常,不是由于语法,而是由于调用 Java 端代码的方式,例如由于本应是有效对象的 null 参数。这些会导致其他类型的异常,仍然可以在对 eval 方法的调用周围捕获,但由于这些没有 getLineNumber() 方法,因此无法猜测解释器的位置。

有什么方法可以从 Nashorn 引擎获取最后执行的行吗?

代码大致如下:

try {
    engine.eval( script);       
    // successful
    return -1;
} catch ( ScriptException e)
{
    // the ScriptException reports the line number
    return e.getLineNumber();
}
catch ( Exception e)
{
    // is it possible to get the line number here too?
    // ... 
    return lineNumber;
}

您可以遍历异常堆栈,找到 class 名称以 jdk.nashorn.internal.scripts. 开头的第一个 StackTraceElement 并报告其行号:

   for(StackTraceElement ste: e.getStackTrace()) {
       if (ste.getClassName().startsWith("jdk.nashorn.internal.scripts.")) {
           return ste.getLineNumber();
       }
   }
   return -1; // couldn't figure it out

如果 ste.getFileName().endsWith(".js") 更适合您的情况,您也可以尝试使用 ste.getFileName().endsWith(".js")

有一个标准的 Nashorn API 可以从给定的任意 Throwable 对象中获取 "script frames" 的 StackTraceElement[]。

jdk.nashorn.api.scripting.NashornException class 有

public static StackTraceElement[] getScriptFrames(可抛异常)

方法

https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/NashornException.html#getScriptFrames-java.lang.Throwable-

您可以传递任意 Throwable 对象并返回脚本框架的 StackTraceElement 数组。最顶部的脚本框架将是数组的第零个元素,您可以在 StackTraceElement 对象上调用 getLineNumber。

这样,您就可以避免对 nashorn 内部包前缀的依赖。