C ++调用Java对象方法:访问冲突

时间:2011-03-14 13:26:08

标签: java jvm java-native-interface

我正在尝试为声音流类实现Java / C ++绑定。为了保持我的例子简单,我将把它简化为它的搜索方法,这足以描述我的问题:

public abstract class JSoundStream extends SoundStream {
    public abstract void seek(float timeOffset);
}

为了测试,我使用以下实现:

@Override public void seek(float timeOffset) {
    System.out.println("seek(" + timeOffset + ")");
}

seek方法是一种回调方法,由本机C ++函数委托,该函数用作播放流的任何内容的回调。以具有快进功能的媒体播放器应用程序为例:

按下“快进”按钮 - >流媒体库调用C ++回调seek - >委托Java方法seek

注意这只是一个例子,事件调度线程和其他任何其他功能都没有。

当创建JSoundStream的实例时,将调用本机方法,该方法将同时保存Java VM指针(JavaVM*)以及Java对象引用(jobject) 。我这样做是因为我无法控制何时调用回调,并且我知道无法获得JNI环境或没有Java引用的 live 对象。所以我在创建对象时保存了这些信息,在那里我有参考文献。

在C ++ seek方法内部,我试图以这种方式调用Java seek方法:

virtual void OnSeek(float timeOffset) {
    JNIEnv* env;
    jvm->AttachCurrentThread((void**)&env, NULL);
    env->CallVoidMethod(binding, m_seek, (jfloat)timeOffset);
}

其中bindingjobjectjvm Java VM指针和m_seek我之前获得的jmethodID方法的seek

但是,CallVoidMethod的调用将导致jvm.dll中的访问冲突。所有的指针和值对我能说的都有效,并确保Java对象不会被垃圾收集。我相信存储jobject和/或Java VM指针是问题的根源,但是我再也看不清楚原因,因为这些值在程序运行时没有变化。

有人看到我接近这个问题的方式有问题吗?如何 - 如果没有存储引用 - 我会从C ++代码调用Java对象方法吗?

1 个答案:

答案 0 :(得分:3)

如果

,您的方法应该是正确的
  1. 已使用binding = env->NewGlobalRef(binding_passed_as_argument);

  2. 检索您的作业
  3. 您不会多次从同一个线程调用AttachCurrentThread - 使用TLS存储JNIEnv指针。