【发布时间】:2019-05-02 13:46:10
【问题描述】:
我正在使用 GraalVM 执行 JavaScript 文件,但在异常处理方面遇到了问题。我的 JS 代码调用回 Java,如果从这些 Java 方法之一抛出异常,那么我会丢失原因链。
public class Example {
public static void doSomething() {
throw new RuntimeException("Example", new RuntimeException("Some nested exception"));
}
}
// --------------
var Example = Java.type("ex.Example");
function f() {
Example.doSomething();
}
// -------------
String src = ...
Source s = Source.newBuilder("js", src, "example").build();
try {
context.eval(s);
} catch (PolyglotException e) {
e.printStackTrace(); // This only prints the PolyglotException with the message "Example"
}
发生这种情况的原因是因为 Graal/Truffle 创建了一个 HostException 的实例,它有一个不调用 super(e) 的构造函数,它将它分配给一个用于获取消息的内部字段,而不是其他任何东西。这似乎是故意的,但我不明白原因。这是安全问题吗?你能想出一种方法来改变这种行为吗?我非常希望在我的日志中提供异常的全部原因,但目前它停在HostException,它通常只是说类似“A”(例如,如果错误是NoSuchElementException("A"))
final class HostException extends RuntimeException implements TruffleException {
private final Throwable original;
HostException(Throwable original) {
this.original = original;
}
Throwable getOriginal() {
return original;
}
@Override
public String getMessage() {
return getOriginal().getMessage();
}
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
public Node getLocation() {
return null;
}
public boolean isCancelled() {
return getOriginal() instanceof InterruptedException;
}
}
【问题讨论】:
-
伙计,你找到打印原因链的方法了吗?
-
@Mirian 有点误解了这种情况。您可以通过读取(或重新抛出)
asHostException()从PolyglotException获取原始异常。你应该先检查isHostException(),如果那是false,那么这是一个javascript错误,并且没有Java-land异常可以获取