java - C++调用Java对象方法: Access Violation

标签 java jvm java-native-interface

我正在尝试为声音流类实现 Java/C++ 绑定(bind)。为了简单起见,我将其简化为它的求法,这足以描述我的问题:

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++ 函数委托(delegate),用作播放流的回调。以具有快进功能的媒体播放器应用为例:

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

请注意,这只是一个示例,既不涉及事件调度线程,也不涉及任何其他时髦的东西。

JSoundStream 的实例被创建时,将调用一个本地方法来保存 Java VM 指针 (JavaVM*) 以及 Java 对象引用(作业对象)。我这样做是因为我无法控制调用回调的确切时间,而且我不知道如何在没有任何 Java 引用的情况下获取 JNI 环境或对象 Activity 。所以我在创建对象时保存了这些信息,我确实有引用。

在 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_seekjmethodID 我之前得到的seek方法。

但是,CallVoidMethod 的调用将导致 jvm.dll 中的访问冲突。我所说的所有指针和值都是有效的,而且我确实确保 Java 对象不会被垃圾回收。我相信存储 jobject 和/或 Java VM 指针是问题的根源,但我又不明白为什么,因为这些值在程序运行时没有改变。

有人能看出我处理这个问题的方式有问题吗?在不存储引用的情况下,我还能如何从 C++ 代码调用 Java 对象方法?

最佳答案

你的方法应该是正确的,如果

  1. 您的工作项目已通过 binding = env->NewGlobalRef(binding_passed_as_argument);

  2. 检索到
  3. 不要从同一线程多次调用 AttachCurrentThread - 使用 TLS 来存储 JNIEnv 指针。

关于java - C++调用Java对象方法: Access Violation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5299168/

相关文章:

java - SpringBoot 1.2.1 MongoRepository

java - 将 RGB 转换为位图中的 X 和 Y

android - 如何编译 Telegram jni文件夹

enums - 保持 native C++ 枚举和 Java 枚举同步

Java正则表达式,在标点符号处分割字符串(括号内除外)

java - 如何解决生产系统上的内存不足错误

java - 在 Java 中调用的 Flex 编译器 mxmlc 导致 64 位 JVM 崩溃 (dcpr.dll)

Java:类路径 JVM 上的多个资源中的哪一个?

java - C-JNI 返回 2D int 数组作为 JobjectArray

java - 单击按钮时,下载 PDF 形式的 jsp 表