【问题标题】:Android JNI C++ Code always get "same" jobject value for 2 different SurfaceView objectAndroid JNI C++ 代码总是为 2 个不同的 SurfaceView 对象获取“相同”的对象值
【发布时间】:2015-07-03 15:17:41
【问题描述】:

在 Android JAVA 代码中:

public native int addRenderer(int channel, Object glSurface);

Context context = getApplicationContext();
SurfaceView svRemotePartyA = new SurfaceView(context);
SurfaceView svRemotePartyB = new SurfaceView(context);

addRenderer(0, svRemotePartyA);
addRenderer(1, svRemotePartyB);

在 Android JNI C++ 代码中:

extern "C" jint JNIEXPORT JNICALL Java_addRenderer(
    JNIEnv* jni, 
    jobject j_vie, 
    jint channel,
    jobject surface) {

    LOG(LS_INFO) << "Java_addRenderer(): surface=" << surface;
    // some processing
}

当我运行程序时,我总是阅读以下日志!两个 SurfaceView 对象在 JNI C++ 代码日志输出中具有相同的值:

(render_manager.cc:175): Java_addRenderer(): surface==0xbeed6120
(render_manager.cc:175): Java_addRenderer(): surface==0xbeed6120

有什么问题?

【问题讨论】:

  • System.out.println(System.identityHashCode(svRemotePartyA) + " " + System.identityHashCode(svRemotePartyB) ) 的输出是什么?在实例化之后、第一次调用 addRenderer 之前和之后以及第二次调用之前和之后。

标签: java android java-native-interface surfaceview


【解决方案1】:

您查看的是本地引用,它永远不应该在同一个 JNI 方法的上下文之外使用。如果您获得此作业的全局参考,您将获得 2 个不同的参考。

【讨论】:

  • 太棒了!谢谢亚历克斯。我得到了他们的全球参考,他们确实是不同的。
  • 如果您为 same 作业获得两个全局引用,它们也可能不同。真正的问题是:打印参考文献的目的是什么?如果试图区分日志消息中的两个对象,最好从对象本身中提取序列号。如果您从 Java 代码中获取对象,则打印全局引用值无济于事,因为方法参数是本地引用......如果您使用的是本机代码中的引用,您已经知道哪个是哪个。
  • @fadden,你说得对,这是一个很好的观点:全局引用的不同十六进制值并不是引用持有不同对象的证据。但如果它们相等,它们肯定指向相同的对象。这不适用于不同 JNI 调用中的本地引用。
  • 我同意:如果您有两个具有相同值的全局引用,那么可以安全地假设它们当时引用了同一个对象。在日志记录中使用它有点问题,因为全局参考值可以重复使用,所以如果您的 Activity 重新启动并且您的对象被重新创建,您可能会看到不同对象的相同 gref 值并做出错误的假设。在处理了许多微妙的破坏代码之后,我条件反射地反对使用 JNI 引用做任何事情,除了将它们传递回 VM 之外。我还担心创建不必要的全局引用(内存泄漏问题)。
【解决方案2】:

您不应尝试将含义与 JNI 引用的特定位模式相关联。

例如,在 Dalvik 中,本地引用只是堆栈上表的索引。如果您对不同的对象多次进行相同的调用,每次都会看到相同的引用“值”,因为对象引用位于本地引用表中的相同位置。

(并不是那么简单——Dalvik 实际上在引用中塞入了一个微不足道的序列号,以便更容易判断在回收后何时使用本地引用——但你明白了。)

同样,您不能对全局引用做出假设。如果您为同一个对象创建两个全局引用,那么这些引用很可能具有不同的 32 位值。

每个虚拟机都是不同的。 Dalvik 的旧(ICS 之前)版本实际上传递了原始指针,您可以比较引用值以确定两个对象是否相同。切换到间接引用需要解决一些问题。

如果要判断两个对象是否相同,则需要对两者都有引用,并使用 JNI IsSameObject() 函数。

一些额外的背景是here

【讨论】:

  • 感谢法登!你的回答真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-19
  • 2020-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
相关资源
最近更新 更多