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

时间:2016-08-02 18:57:52

标签: java java-8 nashorn

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

该程序的任务之一当然是在遇到时向用户报告与脚本有关的任何错误。如果发生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;
}

2 个答案:

答案 0 :(得分:1)

您可以遍历异常堆栈,找到类名称以StackTraceElement开头的第一个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")

答案 1 :(得分:1)

有一个标准的Nashorn API可以获取StackTraceElement []用于"脚本帧"来自给定的任意Throwable对象。

jdk.nashorn.api.scripting.NashornException类有

public static StackTraceElement [] getScriptFrames(Throwable exception)

方法

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内部包前缀。