JNI中FindClass失败问题

转自:https://blog.csdn.net/u014411863/article/details/104725516

由于最近需要写一些jni代码,当然也踩了一些坑,现在梳理一下;写jni访问java层时如果FindClass失败,轻则会导致访问java层的方法失败,处理不当时会导致native层崩溃。

究其原因一般由两种:

原因一:
java类名称字符串的格式错误导致,需要注意以下几点:

1、JNI 类名称以软件包名称开头,并用斜线分隔,例如 java/lang/String。
2、果您要查找某个数组类,则需要以适当数量的英文方括号开头,并且还必须用“L”和“;”将该类括起来,因此 String 的一维数组将是 [Ljava/lang/String; 。
3、查找java层的内部类,需要在外部类签名的基础上使用 符号隔开,例如:FindClass(“com/jninewjavaclass/TestT”);
这种情形通常比较简单可以比较快速的定位出来,总的来说就是类签名书写错误导致的问题;

原因二
另一种情况通常出现线多线程中,也就是通常说的多线程FindClass失败问题,或则从native线程调起java层中,但二者出错的原理一致,

android开发者文档上给出的解释大致如下:

FindClass 要在你的代码关联的类加载器中启动类搜索。它会检查调用堆栈,如果你自行创建的线程,这时应用中没有堆栈帧。如果从此线程调用 FindClass,JavaVM 会在“系统”类加载器(而不是与应用关联的类加载器)中启动,因此尝试查找特定于应用的类将失败。

通俗点来来说就是:

JNI 中所有的 findclass 都必须是java调用下来才有效,由别的native线程(C++)直接调起时,由于没有 java 堆栈是不能找到 java的 class的,会导致findClass失败;
解决该问题的方式:
在首次从java层调用下来时,在FindClass成功后,将 jclass对象进行newGlobalRef 保存起来,后面再次使用时使用该成员变量即可;

参考文档:

https://developer.android.com/training/articles/perf-jni#faq_FindClass

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文原文是:http://developer.android.com/training/articles/perf...
    码农突围阅读 6,382评论 0 11
  • 个人主页:https://chengang.plus/文章将会同步到个人微信公众号:Android部落格 1、创建...
    cg1991阅读 4,168评论 0 1
  • Android开发中,由于各种原因(跨平台,高性能,敏感数据处理等),这时候需要用到大家耳熟能详的JNI(Java...
    潇风寒月阅读 3,382评论 0 0
  • Android FFmpeg专题结构[https://www.jianshu.com/p/c20cc21e29df...
    llm_5243阅读 6,365评论 0 0
  • 闲来翻译了一篇官方的JNI Tips,网上看到的翻译版本要么是时间久了不同步了,要么翻译的过于生硬,看得我怀疑自己...
    生活简单些阅读 5,794评论 1 4