问:在Android系统上运行时,有四个主要异常会导致应用程序崩溃并退出。
答:runtimeException。
ANR。
JNI类和我们自己编写的C代码生成的信号异常。
由第三方so数据包引起的本机信号异常。
因为我们公司的应用程序绝对不需要崩溃退出,所以我着手处理这四种异常,第一种非常容易处理(通过继承Uncaught Exception Handler;通过侦听ANR广播系统;或者通过将C编写为模仿Java中的try-cache函数来捕获信号异常并进行处理),第四个比较困难。
捕获本机异常需要两个步骤
在C的底部捕获本机信号
After receiving the native signal, the signal processing function in C layer calls the method in Java through reflection.
在C的底部捕获本机信号也非常简单。它可以通过信号进行注册。接收到本机信号后,它将直接进入信号处理功能。
最麻烦的是第二步,如何反思。
当前的问题
当前的问题是如何在接收到本地信号后如何通过反射在C语言的信号处理功能中调用Java中的方法。
通过通用C层中的反射来调用Java层的方法没问题,但是当前的问题是在信号处理函数中无法调用它,或者它没有任何作用,因为当捕获信号时,原始进程将很快关闭。
到目前为止,我尝试过的方法是
在信号处理功能中,调用原始活动的方法不容易使用。
在信号处理功能中,调用另一个进程的活动(在清单文件中配置该进程)的方法不容易使用。
在信号处理功能中,将引发并且不能引发异常。
在信号处理函数中,可以引发异常(提前取消默认的关闭操作),但不会被Java层中的异常捕获类捕获(但不能在信号处理函数中引发)捕获并处理)。
部分C代码
void debug(const char *format, ... ) {
va_list argptr;
va_start(argptr, format);
__android_log_vprint(ANDROID_LOG_ERROR, "NATIVE_LIB", format, argptr);
va_end(argptr);
}
static JNIEnv *env;
static jobject obj;
static jclass clazz;
static jmethodID methodID;
//------------------------------------- C abnormal signal acquisition, complex acquisition--------------------------------------------------------------------------------------------------
const int handledSignals[] = {
SIGSEGV, //Signal 11 Invalid Memory Reference
SIGABRT, //Signal 6 Termination Signal from Abrt Function
SIGFPE, //Signal 8 Floating Point Anomalies
SIGILL, //Signal 4 Illegal Directive
SIGBUS, //Signal 7 Bus Error
SIGALRM//Signal 14 Signal from Alarm
};
//const int handledSignalsNum = sizeof(handledSignals) / sizeof(handledSignals[0]);
Enum {handled Signals Num = sizeof (handled Signals) / sizeof (handled Signals [0])}; // Instead of the above, this is used to avoid errors in Variable modified XXXXXX at file scope.
struct sigaction old_handlers[handledSignalsNum];
// When a Native crash occurs and the previous signal anomalies occur, my_sigaction is called to complete the signal processing.
void my_sigaction(int signal, siginfo_t *info, void *reserved) {
// Here catch the native crash
Debug.
//// const char*const message = coffeecatch_get_message();
//// debug ("** FATAL ERROR:% s n", message captured globally";
(* env) - > CallVoid Method (env, obj, methodID, (* env) - > New String UTF (env, "Hello World");
}
int loadSigaction() {
struct sigaction handler;
memset(&handler, 0, sizeof(sigaction));
handler.sa_sigaction = my_sigaction;
// After signal processing, reset to the default processing mode.
// SA_RESTART: Re-initiate syscall interrupted by the signal.
// SA_NOCLDSTOP: Causes the parent process not to receive SIGCHLD signals when its child process pauses or continues.
// SA_NOCLDWAIT: Makes the parent process not receive SIGCHLD signal when its child process exits, and then the child process will not become a zombie process if it exits.
// SA_NODEFER: Invalidates the shielding of the signal, i.e. the signal can still be sent during the execution of the signal processing function.
// SA_RESETHAND: After signal processing, reset to the default processing mode.
// SA_SIGINFO: Use sa_sigaction members instead of sa_handler as signal processing functions.
handler.sa_flags = SA_RESETHAND;
Int i; // for loop I needs to be defined outside otherwise error will be reported
for (i = 0;i < handledSignalsNum; ++i) {
// if(i == 0){
The /// sigaction function is used to change the behavior of a process when it receives a specific signal. If the second and third parameters are set to NULL, the function can be used to check the validity of the signal.
// sigaction (handled signals [i], // representing signal coding) can be any specific and effective signal except SIGKILL and SIGSTOP. Defining their own processing functions for these two signals will lead to signal installation errors.
/& handler, // A pointer to an instance of the structured sigaction that specifies the processing of a particular signal, and if set to null, the process performs the default processing.
// SA_RESTART; // is similar to the parameter act, except that the original processing of the corresponding signal can also be set to NULL.
// } else {
The /// sigaction function is used to change the behavior of a process when it receives a specific signal. If the second and third parameters are set to NULL, the function can be used to check the validity of the signal.
Sigaction (handled signals [i], // representing signal coding) can be any specific and effective signal except SIGKILL and SIGSTOP. Defining their own processing functions for these two signals will lead to signal installation errors.
Handler, // A pointer to an instance of the structured sigaction that specifies the processing of a particular signal, and if set to null, the process performs the default processing.
Old_handlers [i]; // is similar to the parameter act, except that the original signal processing can also be set to NULL.
// }
}
return 1;
}
// Simple handling of simple capture
void handler(int sig){
Debug ("processing");
}
jstring Java_com_wtest_wlib_android_catchs_CatchNativeCrash_loadCatch(
JNIEnv* zenv,
jobject thiz)
{
env = zenv;
obj = thiz;
Load Sigaction (); // Load Capture of JNI Abnormal Signals
// signal (SIGALRM, handler); // Another simple capture method
clazz = (*env)->FindClass(env, "com/wtest/wlib/android/catchs/CatchNativeCrash");
methodID = (*env)->GetMethodID(env, clazz, "show", "(Ljava/lang/String;)V");
(* env) - > CallVoid Method (env, obj, methodID, (* env) - > New String UTF (env, "Hello World");
Char * CSTR = Register Native Signal Capture ok; //jni almost uses this way to define C language strings
Jstring jstr = (* env) - > New String UTF (env, cstr); // Common Writing
return jstr;
}