JNI开发Tips

news2024/11/17 17:31:18

异常的检测和打印:

c++中Native代码调用JNI的时候如果产生了异常不会展开原生堆栈:
所以在c++JNI调用的时候构造一个FindClass时找不到类的异常,我们看到的实际的崩溃堆栈会是下面的样子,看不到c++层代码的调用链路:
在这里插入图片描述
在JNI调用的时候如果遇到了异常,不会立即抛出异常,当代码执行到受管理的代码时会抛出异常。

什么是受管理的代码:使用 Java 或 Kotlin 编程语言编写的代码

在进行异常检测的时候,我们可以使用ExceptionCheck或ExceptionOccurred方法,前者返回的是一个bool值,后者返回的是jthrowable,并没有直接获取jthrowable中异常message的方法,如果需要获取的话需要通过反射,自己在实践的时候使用下面的方法较为方便:

  	if (env->ExceptionCheck()) {
  		// 出现了异常,打印异常堆栈
        env->ExceptionDescribe();
    }

ClassNotFound

在进行JNI开发的时候,可能会遇到的一类问题就是FindClass找不到类,这里我们分两类讨论:

  1. 类被混淆,类名写错:这种自行检查,或者通过工具反编译查看类名称即可解决。
  2. 类找不到的时候查看崩溃的寻找类的path:例如下面的截图,path是 . ,表示当前是在系统类加载器中寻找我们要用的app中的类,这样的话肯定找不到。
    在这里插入图片描述
    解决方案(前三点参考官方给的解决方案):
  • 在 JNI_OnLoad 中执行一次 FindClass 查找,然后缓存类引用以供日后使用。在执行 JNI_OnLoad 过程中发出的任何 FindClass 调用都会使用与调用 System.loadLibrary 的函数关联的类加载器(这是一条特殊规则,用于更方便地进行库初始化)。如果您的应用代码要加载库,FindClass 会使用正确的类加载器。
  • 通过声明原生方法来获取 Class 参数,然后传入 Foo.class,从而将类的实例传递给需要它的函数。
  • 在某个便捷位置缓存对 ClassLoader 对象的引用,然后直接发出 loadClass 调用。这需要花费一些精力来完成。
  • env->GetObjectClass(),通过对象去获取其对应的类,

为什么FindClass会走到系统类加载器呢?查看实现:

static ObjPtr<mirror::ClassLoader> GetClassLoader(const ScopedObjectAccess& soa)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ArtMethod* method = soa.Self()->GetCurrentMethod(nullptr);
  // If we are running Runtime.nativeLoad, use the overriding ClassLoader it set.
  if (method == jni::DecodeArtMethod(WellKnownClasses::java_lang_Runtime_nativeLoad)) {
    return soa.Decode<mirror::ClassLoader>(soa.Self()->GetClassLoaderOverride());
  }
  // If we have a method, use its ClassLoader for context.
  if (method != nullptr) {
    return method->GetDeclaringClass()->GetClassLoader();
  }
  // We don't have a method, so try to use the system ClassLoader.
  ObjPtr<mirror::ClassLoader> class_loader =
      soa.Decode<mirror::ClassLoader>(Runtime::Current()->GetSystemClassLoader());
  if (class_loader != nullptr) {
    return class_loader;
  }
  // See if the override ClassLoader is set for gtests.
  class_loader = soa.Decode<mirror::ClassLoader>(soa.Self()->GetClassLoaderOverride());
  if (class_loader != nullptr) {
    // If so, CommonCompilerTest should have marked the runtime as a compiler not compiling an
    // image.
    CHECK(Runtime::Current()->IsAotCompiler());
    CHECK(!Runtime::Current()->IsCompilingBootImage());
    return class_loader;
  }
  // Use the BOOTCLASSPATH.
  return nullptr;
}

上面的if (method != nullptr) { 判断是否有Java堆栈帧,没有的话就走到下面的GetSystemClassLoader得到系统的类加载器,因此就找不到app中的类,当我们使用从c++层的线程去执行FindClass的时候会遇到上述问题,大家可以参考上面的解决方案尝试解决。
参考:
https://blog.csdn.net/u013989732/article/details/80707607
https://developer.android.com/training/articles/perf-jni?hl=zh-cn#faq:-why-didnt-findclass-find-my-class

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/634334.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Reids】搭建主从集群以及主从数据同步原理

目录 一、搭建主从集群 1、介绍 2、搭建 二、数据同步原理 1、全量同步 2、主节点如何判断是不是第一次连接 3、增量同步 4、优化主从数据同步 一、搭建主从集群 1、介绍 单节点的Redis并发能力存在上限&#xff0c;要提高并发能力就需要搭建主从集群&#xff0c;实现…

WinDbg安装入坑2(C#)

由于作者水平有限&#xff0c;如有写得不对的地方&#xff0c;请指正。 使用WinDbg的过程中&#xff0c;坑特别的多&#xff0c;对版本要求比较严格&#xff0c;如&#xff1a; 1 32位应用程序导出的Dump文件要用32位的WinDbg打开&#xff0c;想要没有那么多的问题&#xf…

数据库存储过程和函数

MySQL存储过程和存储函数 MySQL中提供存储过程&#xff08;procedure&#xff09;与存储函数&#xff08;function&#xff09;机制&#xff0c;我们先将其统称为存储程序&#xff0c;一般的SQL语句需要先编译然后执行&#xff0c;存储程序是一组为了完成特定功能的SQL语句集&…

惊人!截至6月10日全球COVID-19疫情玫瑰图,这些国家最危险

一、引言 自从COVID-19疫情在2020年爆发以来&#xff0c;数据可视化成为了了解疫情趋势和规模的重要手段。饱受争议的疫情数据可视化中的南丁格尔玫瑰图&#xff08;Rose Chart&#xff09;&#xff0c;由于具有简洁、直观、易于理解等特点&#xff0c;逐渐成为了一个备受欢迎的…

MySQL中索引失效的场景

1.对索引使用左或者左右模糊匹配 当我们使用左或者左右模糊匹配的时候&#xff0c;也就是 like %xx 或者 like %xx% 这两种方式都会造成索引失效。 比如下面的 like 语句&#xff0c;查询 name 后缀为「林」的用户&#xff0c;执行计划中的 typeALL 就代表了全表扫描&#xf…

什么是SOME/IP-SD?

SOME/IP-SD 是"Scalable service-Oriented MiddlewarE over IP - Service Discovery"的缩写&#xff0c;是SOME/IP的一种特殊报文&#xff0c;可以让Client知道Server可以提供哪些服务&#xff0c;SOME/IP有两种动态发现服务的机制&#xff1a;一种是Offer Service&a…

Javascript作用域 (局部作用域和全局作用域) 详细介绍

Javascript作用域 (局部作用域和全局作用域) 详细介绍 作用域是当前的执行上下文&#xff0c;值和表达式在其中“可见”或可被访问。 常见的作用域为&#xff1a; 全局作用域&#xff1a;脚本模式运行所有代码的默认作用域 函数作用域&#xff1a;由函数创建的作用域 局部作用域…

IP-Guard上传软件到软件中心服务器时,软件ID、显示名称等信息如何获取?

如何实现客户端只能从软件中心下载安装软件? 控制台设置禁止全部软件安装的软件管理策略即可。即使设置禁止,软件中心安装不会受影响的。 在控制台-策略-软件安装管理策略,勾选禁止全部软件的安装。 软件中心客户端下载安装软件后,下载安装包是否会自动删除? 1、http方式…

SpringBoot Actuator详解(四十八)

还是要开心的&#xff0c;万一梦想真得实现了呢 上一章简单介绍了SpringBoot日志配置(四十七) , 如果没有看过,请观看上一章 本章节详细参考了: https://www.cnblogs.com/caoweixiong/p/15325382.html Spring Boot Actuator 模块提供了生产级别的功能&#xff0c;比如健康检查…

.locked加密勒索数据库级别恢复---惜分飞

有客户数据库被加密成.locked结尾的扩展名,数据库无法正常使用 对应的READ_ME1.html文件中信息类似:send 0.1btc to my address:bc1ql8an5slxutu3yjyu9rvhsfcpv29tsfhv3j9lr4. contact email:servicehellowinter.online,if you can’t contact my email, please contact some d…

Leetcode-6425. 找到最长的半重复子字符串

题目描述 给你一个下标从 0 开始的字符串 s &#xff0c;这个字符串只包含 0 到 9 的数字字符。 如果一个字符串 t 中至多有一对相邻字符是相等的&#xff0c;那么称这个字符串是 半重复的 。 请你返回 s 中最长 半重复 子字符串的长度。 一个 子字符串 是一个字符串中一段…

Redis第十章 Redis HyperLogLog与事务、Redis 7.0前瞻

HyperLogLog HyperLogLog(Hyper[ˈhaɪpə])并不是一种新的数据结构(实际类型为字符串类型)&#xff0c;而是一种基数算法,通过 HyperLogLog 可以利用极小的内存空间完成独立总数的统计&#xff0c;数据集可以是 IP、Email、ID 等。 如果你的页面访问量非常大&#xff0c;比如…

JUC基础认识(2)

线程池(重点)&#xff1a;3大方法&#xff0c;7大参数&#xff0c;4种拒绝策略 程序运行的本质:占用系统资源&#xff01;优化资源的使用&#xff01;----->池化技术 池化技术的好处: 1.降低资源的消耗 2.提高响应速度 3.方便管理 线程复用&#xff0c;可以控制最大…

Java ~ Reference ~ FinalizerHistogram【总结】

前言 文章 相关系列&#xff1a;《Java ~ Reference【目录】》&#xff08;持续更新&#xff09;相关系列&#xff1a;《Java ~ Reference ~ FinalizerHistogram【源码】》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;相关系列&#xff1a;《Java ~ Referenc…

通俗讲解元学习(Meta-Learning)

元学习通俗的来说&#xff0c;就是去学习如何学习&#xff08;Learning to learn&#xff09;,掌握学习的方法&#xff0c;有时候掌握学习的方法比刻苦学习更重要&#xff01; 下面我们进行详细讲解 1. 从传统机器学习到元学习 传统的机器学中&#xff0c;我们选择一个算法&…

Fiddler汉化(一箭三连)

我安装的fiddler 操作系统是&#xff1a;Win10 64Bit 操作系统的版本号是&#xff1a;v5.0.20194.41348 for .NET 4.6.1 fiddler下载地址&#xff1a; 我用夸克网盘分享了「02-Web调试工具-FiddlerSetup.exe」&#xff0c;点击链接即可保存。 链接&#xff1a;https://pan.quar…

python调用go语言的代码

最近在学习上述Python&#xff0c;go语言&#xff0c;研究下互相调用的事项&#xff0c;在windows下使用 linux下&#xff1a; gcc -o libpycall.so -shared -fPIC pycall.c windows下&#xff1a; gcc -o libpycall.dll -shared -fPIC pycall.c 但是实际的过程中编译成*.so…

使用扩展卡尔曼滤波(EKF)融合激光雷达和雷达数据(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

复习js的Object.defineProperty()

今天在看尚硅谷的Vue2时&#xff0c;讲到了Object.defineProperty()方法&#xff0c;有点忘了&#xff0c;所以找资料复习了一下。 总说 Object.defineProperty()是一种用于定义对象属性的JavaScript方法&#xff0c;它允许开发人员精确控制一个属性的行为&#xff0c;并可以…

【MySQL】库表的基本操作

文章目录 数据库的基本操作增查删改切入查看当前使用数据库 数据表的基本操作增查所有表查指定表查表字段信息删表改表名改字段名改字段属性增字段删字段 数据表的约束主键约束(PRIMARY KEY)非空约束(NOT NULL)默认值约束(DEFAULT)唯一性约束(UNIQUE)外键约束(FOREIGN KEY)删除…