具有相同地址,IsSameObject无效的不同Java对象以及相关的全局引用管理问题

时间:2016-01-25 11:42:58

标签: android-ndk java-native-interface

我已经在这个问题上敲了一个星期,现在我开始明白发生了什么,但不知道为什么,或者如何解决它。

让我描述一下我在做什么。我在Java中有各种各样的对象,我有一个本机库。 Java对象通过调用NativeLibrary.AddObject(this)告知库它们的存在。本机库有一个容器jobject,其中我存储了对env->NewGlobalRef(object)获得的Java对象的全局引用。本机库使用这些存储的引用来访问Java对象,它确实可以正常工作。

这是关键部分不起作用。显然,我希望能够删除Java对象,而不仅仅是添加它们。因此,当不再需要Java对象时,它会调用NativeLibrary.RemoveObject(this)。本机库通过迭代存储对象列表(您可能记得都是全局引用)并找到与env->IsSameObject(passedObject, storedObjectGlobalReference)的匹配来实现它。
这就是问题所在:它不能按预期工作,Java对象不能正确匹配它们的全局引用。当我开始使用所有参数挖掘并记录所有调用时,我注意到一个奇怪的事情:本机调用的jobject参数(Java对象的this)对于不同的对象具有相同的值!而且,这个值在``NativeLibrary.AddObject(this)and NativeLibrary.RemoveObject(this)`之间变化,调用同一个对象!

那么,发生了什么,以及如何在本机代码中存储,跟踪和删除对Java对象的引用?重申:只要我只创建和存储全局引用,一切正常;正确的对象通过这些引用接收通知,没问题。但是,当我尝试通过env->DeleteGlobalRef删除这些引用时,我发现NativeLibrary.RemoveObject(this)实现无法匹配存储的对传递的jobject的引用。

1 个答案:

答案 0 :(得分:0)

我也遇到同样的问题。根本原因是当我调用NativeLibrary.AddObject(this)时添加的项NativeLibrary.RemoveObject(this)不是同一对象。我使用的是junit,这引起了问题,因为junit创建了多个对象来运行每个测试。我在Java端将System.out.printlnobject一起使用时发现了问题。在添加功能System.out.println("add object: " + sameObject);之前和在删除功能System.out.println("remove object: " + sameObject);之前。对不起,英语不好,我希望这对某人有帮助。