当某个延迟部分(例如 setTimeout 或 process.nextTick)中发生异常时,使用 J2V8 的 java 应用程序崩溃
A java application with J2V8 crashes when an exception happened in a some deferred section (e.g. setTimeout or process.nextTick)
我使用了很棒的J2V8 java 库,它允许在您的 Java 应用程序中执行任何 Java 脚本代码,此外它还可以集成 nodeJS 引擎。
但是我遇到了下一个问题。此代码在 nodejs 调用 setTimeout 的回调函数后立即中断 Java 应用程序,尽管存在 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
另一个例子表明,异常并不总是导致应用程序中断的原因,而是 'normal' 的情况。
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块中,你可以在它下面看到trace stack。所以中断是在本机方法(第二个示例)中触发的,但在第一种情况下,JS 异常只是杀死了 Java 应用程序,而没有在控制台或跟踪日志中进行任何解释。
您在 java 脚本代码中抛出的错误似乎正在传播到 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);
这是最佳且正确的解决方案。
process.on('unhandledRejection', (err) => {
console.error('Unhandled promise rejection',err);
});
process.on('uncaughtException', (err) => {
console.error('Uncaught exception',err);
});
有关更多信息,请参阅 nodeJS 文档:Event: 'uncaughtException'
我使用了很棒的J2V8 java 库,它允许在您的 Java 应用程序中执行任何 Java 脚本代码,此外它还可以集成 nodeJS 引擎。
但是我遇到了下一个问题。此代码在 nodejs 调用 setTimeout 的回调函数后立即中断 Java 应用程序,尽管存在 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
另一个例子表明,异常并不总是导致应用程序中断的原因,而是 'normal' 的情况。
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块中,你可以在它下面看到trace stack。所以中断是在本机方法(第二个示例)中触发的,但在第一种情况下,JS 异常只是杀死了 Java 应用程序,而没有在控制台或跟踪日志中进行任何解释。
您在 java 脚本代码中抛出的错误似乎正在传播到 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);
这是最佳且正确的解决方案。
process.on('unhandledRejection', (err) => {
console.error('Unhandled promise rejection',err);
});
process.on('uncaughtException', (err) => {
console.error('Uncaught exception',err);
});
有关更多信息,请参阅 nodeJS 文档:Event: 'uncaughtException'