3

在解决这个问题几天后,我目前正在头撞我的办公桌。

我的原生 android 应用程序在运行时加载了一个类,我按照本教程从 assets 文件夹中获取 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"); 

任何帮助都会令人难以置信,干杯人

4

1 回答 1

1

好吧,这里有很多东西。

首先,正如@Alex Cohn 所说,我们需要保留使用“全局引用”轻松完成的类,这将使作业对象(或 jclass 等)在发布之前不会被重新分配。我认为这种效果是线程本地的,因为这是一些早期版本的 android 中的效果(据我所知)

接下来,出于我不会在这里让您感到厌烦的原因,我们正在使用DexClassloader,因为我们正在从资产文件夹加载我们的 apk (请参阅此处了解其工作原理),因此我们还需要保持这一点。FindClass 只能在它自己的上下文中工作,它用于加载系统类(尽管如果你这样做,你可以加载你自己的)

现在我们需要能够在每个线程中使用来自 apk 的类,因此当我们为每个线程创建 JniEnv 并使用pthread_key缓存它时,我们运行 declassloader.loadclass 。这样我们就可以在任何地方获取类,并通过 keythread 回调自动进行释放。

无论如何,这已经足够了。祝你好运!

ps 附带说明,一旦 jni 方法抛出了一个未经处理的异常,您无法保证任何其他调用都会起作用......有些会,有些不会,有些会导致段错误......所以从 java 方面自由地捕捉并保护本机端免受 Java 的肮脏!

于 2013-10-01T10:47:17.733 回答