简体   繁体   English

当某个延迟部分发生异常时,J2V8的Java应用程序崩溃(例如setTimeout或process.nextTick)

[英]A java application with J2V8 crashes when an exception happened in a some deferred section (e.g. setTimeout or process.nextTick)

I use amazing J2V8 java library which allows execute any Javascript code in your Java application furthermore it can integrates a nodeJS engine. 我使用了令人惊叹的J2V8 java库,它允许在Java应用程序中执行任何Javascript代码,此外它还可以集成nodeJS引擎。

But i have encountered with a next issue. 但我遇到了下一个问题。 This code interrupts a Java application immediately after nodejs invokes a callback function of setTimeout which throw an exception although there is a try..carch block. 这个代码在nodejs调用setTimeout的回调函数后立即中断Java应用程序,虽然有一个try..carch块,但它会抛出异常。 The exception doesn't even enter into the try..catch block. 该异常甚至没有进入try..catch块。

// It is an example, in real case it can be a some erorr in a code.
nodeJS = NodeJS.createNodeJS();
try {
    nodeJS.getRuntime().executeVoidScript("setTimeout(function(){throw 'Error'}, 1000);"); 
} catch (Exception e) {
    e.printStackTrace();
}

The application is interrupted with message: 应用程序中断消息:

undefined:1
setTimeout(function(){throw 'Error'}, 10000);
                  ^
Error
Process finished with exit code 1

Another example shows that exceptions are not a cause of interruption of an application always and it is a 'normal' case. 另一个例子表明异常不是导致应用程序中断的原因,而是一个“正常”的情况。

nodeJS = NodeJS.createNodeJS();
try {
    nodeJS.getRuntime().executeVoidScript("throw 'Error'");
} catch (Exception e) {
    e.printStackTrace();
}

In this case we see the only a error message in console but the application still works. 在这种情况下,我们在控制台中看到唯一的错误消息,但应用程序仍然有效。

Exception in thread "Thread-2" undefined:1: Error
throw 'Error'
^
com.eclipsesource.v8.V8ScriptExecutionException
    at com.eclipsesource.v8.V8._executeScript(Native Method)
    at com.eclipsesource.v8.V8.executeScript(V8.java:940)
    at com.eclipsesource.v8.V8.executeScript(V8.java:595)
    at com.eclipsesource.v8.V8.executeObjectScript(V8.java:625)
    at com.eclipsesource.v8.V8.executeObjectScript(V8.java:608)
    at org.efc.origamiapp.v8.V8Environment.run(V8Environment.java:383)

The examples above are in the try..catch blocks, and you can see trace stack below it. 上面的示例位于try..catch块中,您可以在其下方看到跟踪堆栈。 So the interruption is fired in Native Method (the secod example), but in the first case the JS exception just kills the Java application without any explanations in a console or in a trace log. 因此,在Native Method(secod示例)中触发了中断,但在第一种情况下,JS异常只是在控制台或跟踪日志中没有任何解释的情况下杀死Java应用程序。

It looks like the error you are throwing in the javascript code is being propagated into the java environment. 看起来你在javascript代码中抛出的错误正在传播到java环境中。 This is what one would expect to see given the js code you are trying to execute ( throw 'Error' ). 鉴于您尝试执行的js代码( throw 'Error' ),这是人们期望看到的。 What did you expect to happen? 你期望发生什么? Simply catch any exceptions in java and handle appropriately - maybe by logging? 只需捕获java中的任何异常并适当处理 - 也许通过记录?

try {
    nodeJS.getRuntime().executeVoidScript("throw 'Error'"); 
}
catch(Exception e) { 
    System.out.println(e.toString()); 
}

This is the best and correct solution. 这是最好和正确的解决方案。

process.on('unhandledRejection', (err) => {
    console.error('Unhandled promise rejection',err);
});
process.on('uncaughtException', (err) => {
    console.error('Uncaught exception',err);
});

For more information see the nodeJS documentation: Event: 'uncaughtException' 有关更多信息,请参阅nodeJS文档: 事件:'uncaughtException'

For now my workaround is this script. 现在我的解决方法是这个脚本。

let nativeSetTimeout = setTimeout;
setTimeout = function(fn, t){
    let safeFn = () => {
        try {
            fn();
        } catch(e){
            console.log(e);
        }
    };
    return nativeSetTimeout(safeFn,t);
} 


let nativeNextTick = process.nextTick;
process.nextTick = function(){
    let args = Array.prototype.slice.call(arguments);
    let fn = args[0];
    let safeFn = () => {
        try {
            fn.apply(null,args.slice(1));
        } catch(e){
            console.log(e);
        }
    };
    return nativeNextTick(safeFn);
}

I invoke this script in a beginning of an application. 我在应用程序的开头调用此脚本。

nodeJS.getRuntime().executeVoidScript(workaroundScript);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM