问题
I'm using GraalVM to execute JavaScript files, but i'm having trouble with exception handling. My JS code makes calls back into Java, and if an exception is thrown from one of those Java methods then i lose the cause-chain.
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"
}
The reason this happens is because Graal/Truffle makes an instance of HostException
, which has a constructor that doesn't call super(e)
, it assigns it to an internal field that's used to get the message and nothing else. It seems to have been done intentionally, but i don't understand the reason. Is it a security concern? Can you think of a way i can change this behaviour? I would very much like to have the full cause of the exception available in my logs, but at the moment it stops at the HostException
, which often just says something like "A
" (eg. if the original cause of the error was 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;
}
}
回答1:
I've faced the same issue and it turned out, that JS Error has the following functions:
printStackTrace: [Function],
fillInStackTrace: [Function],
getCause: [Function],
initCause: [Function],
toString: [Function],
getMessage: [Function],
getLocalizedMessage: [Function],
getStackTrace: [Function],
setStackTrace: [Function],
addSuppressed: [Function],
getSuppressed: [Function]
printStackTrace
, for example, prints java stack trace:
try {
Java.type('ClassWithException').throwRuntimeEx();
} catch (e) {
console.log(e.printStackTrace())
}
gives the following:
java.lang.RuntimeException: Example message
at ex.ClassWithException.throwRuntimeEx(ClassWithException.java:6)
at com.oracle.truffle.polyglot.HostMethodDesc$SingleMethod$MHBase.invokeHandle(HostMethodDesc.java:269)
at com.oracle.truffle.polyglot.HostMethodDesc$SingleMethod$MHBase.invoke(HostMethodDesc.java:261)
at com.oracle.truffle.polyglot.HostExecuteNode$1.executeImpl(HostExecuteNode.java:776)
at com.oracle.truffle.polyglot.GuestToHostRootNode.execute(GuestToHostRootNode.java:87)
at org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callProxy(OptimizedCallTarget.java:328)
...
at com.oracle.truffle.polyglot.PolyglotValue$InteropValue.execute(PolyglotValue.java:2008)
at org.graalvm.polyglot.Value.execute(Value.java:338)
at com.oracle.truffle.trufflenode.GraalJSAccess.isolateEnterPolyglotEngine(GraalJSAccess.java:2629)
Caused by: java.lang.RuntimeException: Inner exception
... 245 more
来源:https://stackoverflow.com/questions/55953882/exception-chains-in-graalvm