Java 在解释过程中获取Nashorn脚本行号

Java 在解释过程中获取Nashorn脚本行号,java,java-8,nashorn,Java,Java 8,Nashorn,我的代码使用Nashorn向用户提供脚本功能,许多类和函数通过Nashorn在Java上实现,并通过脚本公开 当然,程序的任务之一是在遇到与脚本相关的任何错误时向用户报告。如果发生ScriptException,这非常简单,因为只需捕获异常并使用方法getLineNumber()即可返回正确的值。但是,偶尔会出现异常,这不是由于语法,而是由于调用Java端代码的方式,例如,由于假定为有效对象的null参数。这些会导致其他类型的异常,在调用eval方法时仍然可以捕获到这些异常,但是由于这些异常没有

我的代码使用Nashorn向用户提供脚本功能,许多类和函数通过Nashorn在Java上实现,并通过脚本公开

当然,程序的任务之一是在遇到与脚本相关的任何错误时向用户报告。如果发生
ScriptException
,这非常简单,因为只需捕获异常并使用方法
getLineNumber()
即可返回正确的值。但是,偶尔会出现异常,这不是由于语法,而是由于调用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;
}

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

   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”)

有一个标准的Nashorn API,用于从给定的任意可丢弃对象获取“脚本帧”的StackTraceeElement[]

jdk.nashorn.api.scripting.NashornException类具有

公共静态StackTraceeElement[]getScriptFrames(可丢弃异常)

方法

您可以传递任意可丢弃对象,并获取脚本帧的StackTraceeElement数组。最上面的脚本帧是数组的第0个元素,您可以在StackTraceeElement对象上调用getLineNumber

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