This question already has an answer here:
ART prevents any Java calls from JNI during native signal handling
(1个答案)
2年前关闭。
我已经开发了使用 native C库的Android应用程序。我可以使用JNI成功地编译整个程序,并且一切都可以顺利进行。
但是, native C库有时会崩溃(使用SIGSEGV时最常见)。反过来,这导致我的应用程序崩溃,而对用户没有任何有意义的通知。我想实现以下目标:
使用信号处理程序(sigaction)在 native 代码中捕获信号,以防止随机崩溃 在C库中引发Java可以捕获 的异常捕获Java中的异常,为用户生成有意义的警告消息,并保持应用程序运行
如果这对您有用,则JNI代码在单独的线程中运行(更确切地说,在AsyncTask中)。
我已经检查了http://blog.httrack.com/blog/2013/08/23/catching-posix-signals-on-android/和https://github.com/xroche/coffeecatch
但是我无法编译它。
遵循Best way to throw exceptions in JNI code?和How to catch JNI Crashes as exceptions using Signal handling based mechanism in Java和https://www.developer.com/java/data/exception-handling-in-jni.html的建议
我执行了以下步骤:
在我的 native 代码中,我添加了以下函数(据我所知)设置了信号处理程序:
我处理这些信号的函数如下所示:
我关键的JNI功能首先从配置信号处理程序开始:
当我的 native C代码中出现SIGILL时,将发生以下情况:
1)在调试终端上,我收到以下四个消息
Sighandler:4个(对应于SIGILL) 抛出异常 Sighandler:4 Sighandler:11
2)应用程序窗口关闭,但我没有收到Android消息
应用程序崩溃时通常会出现“不幸...已关闭”
我真的不明白为什么我得到第三和第四信号消息,因为我认为抛出了异常。另外,我认为从未真正向Java抛出异常。
我迷路了,任何帮助将不胜感激。
(1个答案)
2年前关闭。
我已经开发了使用 native C库的Android应用程序。我可以使用JNI成功地编译整个程序,并且一切都可以顺利进行。
但是, native C库有时会崩溃(使用SIGSEGV时最常见)。反过来,这导致我的应用程序崩溃,而对用户没有任何有意义的通知。我想实现以下目标:
如果这对您有用,则JNI代码在单独的线程中运行(更确切地说,在AsyncTask中)。
我已经检查了http://blog.httrack.com/blog/2013/08/23/catching-posix-signals-on-android/和https://github.com/xroche/coffeecatch
但是我无法编译它。
遵循Best way to throw exceptions in JNI code?和How to catch JNI Crashes as exceptions using Signal handling based mechanism in Java和https://www.developer.com/java/data/exception-handling-in-jni.html的建议
我执行了以下步骤:
在我的 native 代码中,我添加了以下函数(据我所知)设置了信号处理程序:
void initializeSignalHandler(JNIEnv* env){
int watched_signals[] = { SIGABRT, SIGILL, SIGSEGV, SIGINT, SIGKILL }; // 6, 4, 11, 2, 9
struct sigaction sighandler;
memset(&sighandler, 0, sizeof(sighandler));
sighandler.sa_sigaction = &sighandler_func;
sighandler.sa_mask = 0;
sighandler.sa_flags = SA_SIGINFO | SA_ONSTACK;
for(int ii=0; ii<5; ii++){
int signal = watched_signals[ii];
sigaction(signal, &sighandler, NULL);
}
env = env;
}
我处理这些信号的函数如下所示:
void sighandler_func(int sig, siginfo_t* sig_info, void* ptr){
printerr("Sighandler: ", sig);
jclass jcls = (*env)->FindClass(env, "java/lang/Error");
jboolean flag = (*env)->ExceptionCheck(env);
if (flag) {
(*env)->ExceptionClear(env);
/* code to handle exception */
}
if (jcls!=NULL){
printerr("Throwing exception");
(*env)->ThrowNew(env, jcls, "error message");
}
}
我关键的JNI功能首先从配置信号处理程序开始:
JNIEXPORT jint JNICALL Java_android_playground_criticalFuction
(JNIEnv *env, jclass c, jlong handle, jshortArray out_buffer){
// new signal handler
struct sigaction sighandler;
initializeSignalHandler(env);
// ...here goes the critical code
}
当我的 native C代码中出现SIGILL时,将发生以下情况:
1)在调试终端上,我收到以下四个消息
2)应用程序窗口关闭,但我没有收到Android消息
应用程序崩溃时通常会出现“不幸...已关闭”
我真的不明白为什么我得到第三和第四信号消息,因为我认为抛出了异常。另外,我认为从未真正向Java抛出异常。
我迷路了,任何帮助将不胜感激。
最佳答案
我不知道您在这里尝试做什么在技术上是否可行。 @Michael的评论暗示不可能。
但是,如果可能的话,这是一个坏主意。
当您正在使用的 native 库触发SIGSEGV时,它很可能造成了无法估量的损失;例如覆盖堆中的对象,等等。如果尝试恢复,则先前的损坏可能会导致意外的行为或错误的结果……或者GC稍后会由于堆损坏而崩溃。
这就是为什么在 native 代码或Java代码中发生意外的SIGSEGV时,JVM会 panic 的标准行为。
给用户一个有意义的错误是很好的做法,但是如果您遇到随机的SIGSEGV错误和其他JVM紧急情况,您可以告诉他们并没有太大的意义。
关于java - 在Android上按异常(exception)替换JNI崩溃,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47873847/