在运行时从jar文件加载的类上使用FindClass

3

我在为这个问题苦思冥想了几天,现在正在不停地用头撞桌子。

我的原生Android应用程序在运行时加载一个类,我已经按照这篇教程的指导从资源文件夹中获取了dexed jar文件,并成功地加载了该类并调用了它的静态方法。

然而,如果我运行一个...

env->FindClass("TheClass"); 

...它抛出了一个Java异常。

这里是代码中相关的部分

//this works find and gives me a usable class
jclass shim_class = helper.LoadClassFromAssetsJar("test.jar","TheClass");
// this throws the exception    
jclass refound_shim_class = jni->FindClass("TheClass"); 

任何帮助都将是不可思议的,朋友们加油!

1
这与类加载器有关 - 你可能需要在 JNI_OnLoad 中完成所有的 FindClass 调用,或者在 FindClass 调用中使用正确的类加载器。 - krsteeve
1
请参考https://dev59.com/QWYr5IYBdhLWcg3w8-rA,了解如何解决Android上的[FindClass问题](http://developer.android.com/guide/practices/jni.html#faq_FindClass)。我建议:如果您已经从加载器中获取了类,请保留以备将来使用! - Alex Cohn
1个回答

1

这里的内容相当丰富。

首先,正如 @Alex Cohn 所说,我们需要保留类,这可以使用 '全局引用' 轻松完成,它将使得 jobject(或 jclass 等)在释放之前不会被重新分配。我认为这种效果是线程本地的,因为这是一些早期版本的 Android 中的情况(据我所见)。

下一步,出于我在此不想让你感到厌烦的原因,我们正在使用DexClassloader,因为我们从资产文件夹中加载apk(请参见此处如何工作),所以我们也需要保持这个。FindClass仅在其自己的上下文中起作用,这是为了加载系统类(虽然如果您这样做,可以加载自己的类)
现在我们需要能够在每个线程中使用来自apk的类,因此我们在创建每个线程的JniEnv时运行declassloader.loadclass并使用pthread_key进行缓存。这样我们就可以在任何地方获取该类,并且通过keythread回调自动完成解除分配。
无论如何,就这些了。祝你好运!

附注:一旦JNI方法抛出未处理的异常,您无法保证任何其他调用都能正常工作...有些会,有些不会,有些会导致段错误...因此,请在Java端慷慨地捕获异常并保护本地端免受Java的恶意!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接