本文主要提供在 NDK Android 上面,由于无法避免调用某些 3RD的原生代码,而该程序存在潜在BUG,意思就是会导致NATIVE上面发生错误,崩溃整个程序的一个解决办法。

本方法是基于 LINUX 系统的异常信号捕获来实现的,该方法仍旧可以使用在 Android 平台上面正确工作。

但捕获异常信号确保程序不崩溃,它不意味着不会发生其它不可预料或控制的问题,例如非托管内存资源泄露问题。

需要注意一点该函数必须是在 STAThread (单线程)下运行,否则我们需要为调用该 JNI Native 函数增加代码临界保护。

另外值得一提,请不要随意修改 JNI C/C++ 层面对于该函数的实现,否则可能遇到 JVM 检查到错误导致 JAVA 进程崩溃的问题,理论上 JAVA 是不允许从 JAVA JIT 函数内因为调用到 NATIVE,然后因为NATIVE报错,然后跳回到本NATIVE函数调用堆栈的,但这个东西实现可以说是在卡 BUG,但是卡这个BUG,Android 四个指令集多个发行版,经过验证都可以正确就绪工作。

补充:该方法仅在函数执行期间捕获到崩溃信号,例如35(FD_SCAN,Android特有多次关闭描述符崩溃信号)、SIGSEGV(段错误)才会执行异常跳转回该函数堆栈,这部分是绕过 JAVA 层面调用堆栈【多层函数平衡堆栈逻辑都不被处理】,算是个解决问题的偏方,除非真的没得办法,必须要处理,可以临时考虑这个方案,但不建议长久使用。

例子:

libcor32.c.call(() -> wv.evaluateJavascript(code, cb))

源实现:

JAVA

    public interface ICall {void handle();}public Throwable call(ICall call) {if (call == null) {return new IllegalArgumentException("call");}final Throwable[] throwable = {null};synchronized (libcor32.this) {try {ccall(new ICall() {@Overridepublic void handle() {try {call.handle();} catch (Throwable ex) {throwable[0] = ex;}}});} catch (Throwable ex) {throwable[0] = ex;}}return throwable[0];}private native void ccall(ICall call);

JNI C/C++(NDK)

inline static int signal_watch(int signo, struct sigaction *osas, sighandler_t _call_jmp_handler) {struct sigaction sa;memset(&sa, 0, sizeof(sa));/*init new _call_jmp_handler struct*/sa.sa_handler = _call_jmp_handler;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;return sigaction(signo, &sa, osas);
}inline static int signal_unwatch(int signo, struct sigaction *osas) {return sigaction(signo, osas, NULL);
}__LIBCOR32__(void) Java_com_android_myapp_c_libcor32_ccall(JNIEnv *env,jobject this_,jobject handler_) {static sigjmp_buf _call_jmp_buf;static sighandler_t _call_jmp_handler = [](int signo) {siglongjmp(_call_jmp_buf, signo);};static struct sigaction __call_osas_chunks[15];signal_watch(35, __call_osas_chunks + 0, _call_jmp_handler); // FDSCAN(SI_QUEUE)signal_watch(SIGBUS, __call_osas_chunks + 1, _call_jmp_handler);signal_watch(SIGPIPE, __call_osas_chunks + 2, _call_jmp_handler);signal_watch(SIGFPE, __call_osas_chunks + 3, _call_jmp_handler);signal_watch(SIGSEGV, __call_osas_chunks + 4, _call_jmp_handler);signal_watch(SIGILL, __call_osas_chunks + 5, _call_jmp_handler);signal_watch(SIGTRAP, __call_osas_chunks + 6, _call_jmp_handler);signal_watch(SIGSYS, __call_osas_chunks + 7, _call_jmp_handler);signal_watch(SIGQUIT, __call_osas_chunks + 8, _call_jmp_handler);signal_watch(SIGIOT, __call_osas_chunks + 9, _call_jmp_handler);signal_watch(SIGUSR1, __call_osas_chunks + 10, _call_jmp_handler);signal_watch(SIGUSR2, __call_osas_chunks + 11, _call_jmp_handler);signal_watch(SIGXCPU, __call_osas_chunks + 12, _call_jmp_handler);signal_watch(SIGXFSZ, __call_osas_chunks + 13, _call_jmp_handler);signal_watch(SIGSTKFLT, __call_osas_chunks + 14, _call_jmp_handler);jint err_ = sigsetjmp(_call_jmp_buf, 1);if (err_ == 0) {jclass clazz_ = env->GetObjectClass(handler_);jmethodID method_ = env->GetMethodID(clazz_, "handle", "()V");env->CallVoidMethod(handler_, method_);}signal_unwatch(35, __call_osas_chunks + 0); // FDSCAN(SI_QUEUE)signal_unwatch(SIGBUS, __call_osas_chunks + 1);signal_unwatch(SIGPIPE, __call_osas_chunks + 2);signal_unwatch(SIGFPE, __call_osas_chunks + 3);signal_unwatch(SIGSEGV, __call_osas_chunks + 4);signal_unwatch(SIGILL, __call_osas_chunks + 5);signal_unwatch(SIGTRAP, __call_osas_chunks + 6);signal_unwatch(SIGSYS, __call_osas_chunks + 7);signal_unwatch(SIGQUIT, __call_osas_chunks + 8);signal_unwatch(SIGIOT, __call_osas_chunks + 9);signal_unwatch(SIGUSR1, __call_osas_chunks + 10);signal_unwatch(SIGUSR2, __call_osas_chunks + 11);signal_unwatch(SIGXCPU, __call_osas_chunks + 12);signal_unwatch(SIGXFSZ, __call_osas_chunks + 13);signal_unwatch(SIGSTKFLT, __call_osas_chunks + 14);if (err_ != 0) {LOG_ERROR("Android native call crash error, specific signal: %d, has been processing.",err_);}
}

Android 上面关于不受控制3RD原生代码崩溃问题相关推荐

  1. Android 系统(92)---诊断原生代码崩溃问题

    诊断原生代码崩溃问题 原生代码崩溃问题的类型 以下部分详细介绍了最常见的几类原生代码崩溃问题.每类崩溃问题都包含一段 debuggerd 输出示例,其中的关键证据可以帮助您区分特定类型的崩溃问题(以橙 ...

  2. Android稳定性系列-01-使用 Address Sanitizer检测原生代码中的内存错误

    前言 想必大家曾经被各种Native Crash折磨过,本地测试没啥问题,一到线上或者自动化测试就出现各种SIGSEGV.SIGABRT.SIGILL.SIGBUS.SIGFPE异常,而且堆栈还是崩溃 ...

  3. flutter 调用原生安卓插件_Flutter 如何调用Android和iOS原生代码

    分3个大步骤: 1.在flutter中调用原生方法 2.在Android中实现被调用的方法 3.在iOS中实现被调用的方法 在flutter中调用原生方法 场景,这里你希望调用原生方法告诉你一个boo ...

  4. flutter 调用原生安卓插件_Flutter 如何调用Android和iOS原生代码-阿里云开发者社区...

    分3个大步骤: 1.在flutter中调用原生方法 2.在Android中实现被调用的方法 3.在iOS中实现被调用的方法 在flutter中调用原生方法 场景,这里你希望调用原生方法告诉你一个boo ...

  5. android开发 问卷调查案例_安卓 问卷调查Demo 原生代码

    [实例简介] android 问卷调查Demo,android原生代码,不是webView加载H5,比较容易理解,大家可以改改 [实例截图] [核心代码] QuestionDemo └── Quest ...

  6. React Native调用Android原生代码实现车牌识别功能【附效果图附源码】

    转载请注明出处,原文地址:http://blog.csdn.net/lucherr/article/details/71908180 这段时间研究了下React Native,Facebook推出的, ...

  7. 符号执行android,基于符号执行的android原生代码控制流图提取方法symbolic.pdf

    基于符号执行的android原生代码控制流图提取方法symbolic 第3 卷第7 期 网络与信息安全学报 Vol.3 No.7 2017 年7 月 Chinese Journal of Networ ...

  8. 【Android NDK 开发】NDK C/C++ 代码崩溃调试 - Tombstone 报错信息日志文件分析 ( 使用 addr2line 命令行工具查找动态库中的报错代码位置 )

    文章目录 一.从 Tombstone 报错日志中查找报错动态库 二.addr2line 命令行工具使用 64 位动态库使用的 aarch64-linux-android-addr2line.exe 工 ...

  9. android修改原生代码,【ROM教程】安卓原生ROM修改源码消除WIFI叹号教程

    [ROM教程]安卓原生ROM修改源码消除WIFI叹号教程.Android为了对网络状态进行检测,采用了一种叫做captive detection的方式进行网络状态检测.其实说起来很简单,每当连接到一个 ...

最新文章

  1. Localization
  2. head()函数python_Python中的Pandas DataFrame head()方法
  3. 七十七、SpringBoot整合Rabbitmq
  4. HDU Problem - 4292 Food(最大流, 建边)
  5. python括号的区别_Python中类-带括号与不带括号的区别
  6. 归并排序python实现
  7. .NET中异常类(Exception)
  8. python---之round
  9. CentOS 6.5下安装MySQL后重置root密码方法
  10. 赛码行测题库_在线笔试— 赛码网试题(一)
  11. python攻击校园网_python爬虫 模拟登陆校园网-初级
  12. 经典:智能物联网大数据系统案例
  13. windows11 微信双开的方法
  14. 多元线性回归模型预测房价
  15. 微信小程序之点点考勤经验总结
  16. 【Yolov5】训练yolov5模型并集成到安卓应用中(中)——模型转化
  17. 贪吃蛇小游戏制作(4)
  18. 幼儿园语言活动包括哪几类_幼儿园语言活动形式有哪些
  19. google真的很简单的
  20. python爬虫爬取公众号_Python selenium爬取微信公众号文章代码详解

热门文章

  1. Stream流:基本API操作详细笔记
  2. 苏州大学文正学院JAVA试卷_苏州大学文正学院试题库建设管理办法(试行)
  3. 【一盏灯】利用单片机点亮一盏灯
  4. 【Pygame实战】单机游戏《赛车计划》评测:不一样的汽车题材游戏,除了技术还看运气~(附代码)
  5. 《初等数论》:最大公因数与最小公倍数
  6. 2015年7月29日工作总结
  7. PostgreSQL备份工具pg_dump和pg_dumpall
  8. 个人理解,关于python 的__init__.py 以及 __all__ 的用法
  9. OSError: [Errno 22] Invalid argument: 'E:\\DESK\x08ank dataset\train_set.csv'
  10. 【高等数学】下册 第十二章 第一节 常数项级数的概念和性质