Java-приложение с J2V8 аварийно завершает работу, когда происходит исключение в некотором отложенном разделе (например, setTimeout или process.nextTick)

Я использую удивительную java-библиотеку J2V8, которая позволяет выполнять любой код Javascript в вашем Java-приложении, кроме того, он может интегрировать движок nodeJS.

Но я столкнулся со следующей проблемой. Этот код прерывает Java-приложение сразу после того, как nodejs вызывает функцию обратного вызова setTimeout, которая выдает исключение, хотя есть блок try..carch. Исключение даже не входит в блок 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();
}

Приложение прерывается сообщением:

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

Другой пример показывает, что исключения не всегда являются причиной прерывания работы приложения, и это "нормальный" случай.

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

В этом случае мы видим единственное сообщение об ошибке в консоли, но приложение все еще работает.

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)

Приведенные выше примеры находятся в блоках try..catch, а под ним вы можете видеть стек трассировки. Таким образом, прерывание запускается в Native Method (пример secod), но в первом случае исключение JS просто убивает приложение Java без каких-либо объяснений в консоли или в журнале трассировки.

3 ответа

Решение

Это лучшее и правильное решение.

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

Для получения дополнительной информации см. Документацию по nodeJS: Событие: 'uncaughtException'

Похоже, ошибка, которую вы генерируете в коде javascript, распространяется в среду java. Это то, что можно ожидать, учитывая код js, который вы пытаетесь выполнить (throw 'Error'). Чего ты ожидал? Просто ловите любые исключения в Java и обрабатывайте их соответствующим образом - может быть, войдя в систему?

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

На данный момент мой обходной путь - этот сценарий.

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);
}

Я вызываю этот скрипт в начале приложения.

nodeJS.getRuntime().executeVoidScript(workaroundScript);
Другие вопросы по тегам