当前位置: 首页 > 知识库问答 >
问题:

如何在JNI中从线程内部调用JAVA方法

漆雕和昶
2023-03-14

TL;博士我在通过线程将FFMPEG原始数据从C代码传递到JAVA代码(用于显示)时遇到问题。

有一个服务器可以向其客户端发送编码帧。这些编码的帧是用一些FFMPEG魔法编码的。在客户端接收时,前面提到的帧被解码为原始RGB数据(作为无符号字符*)。现在的问题是,帧在某种“侦听器”中被接收。只要一个线程在后台运行,轮询服务器,并在新帧可用时运行特定的onFrame功能。

当前以视频格式显示帧的解决方案是将每个帧保存到C语言的内部存储器中,然后在java端有一个FileObserver,一旦图像写入内存,它就会立即显示图像。可悲的是,这种方法在手机上产生的视频为6fps,而在服务器上产生的视频为10fps。

我需要一种将无符号字符*(jbytearray)传递到JAVA代码的方法,这样我就可以解码并从RAM而不是磁盘显示它。

值得一提的是,onFrame函数不能有JNIEnv*

到目前为止,我所尝试的是在我的MainActive中创建一个本地方法,通过该方法我可以传递JNIEnvjObject并将它们分配给全局变量

JNIEnv* m_globalEnv = env;
jobject m_globalObject = thiz;
JavaVM m_jvm = 0;
jclass mainActivity = m_globalEnv->GetObjectClass(m_globalObject);
jmethodID testMethod = m_globalEnv->GetMethodID(mainClass, "testMethod", "(I)V");

m_globalEnv->GetJavaVM(&m_jvm);

之后,在我的onFrame中,我调用
jvm-

m_globalEnv->CallVoidMethod(m_globalObject, "testMethod", 5);

然后所有的崩溃与任何:

1- JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xffe8ea7c
2- JNI DETECTED ERROR IN APPLICATION: Thread is making JNI calls without being attached
.
.
.

在从Michael的解决方案中尝试代码后,我得到了
java_vm_ext.cc:542]JNI检测到应用中的错误:使用无效的jject 0xc94f7f8c错误。在调试模式下运行应用程序以捕获错误后,我得到了jni. h;触发错误的代码行是:m_env-


共有1个答案

孙经艺
2023-03-14

我看到了代码的两个潜在问题:

1.跨线程共享一个JNIEnv*
每个本机线程都应该通过将自身连接到JVM,然后在某个时刻分离自身来获得自己的JNIEnv*。有关更多详细信息和可能的解决方案,请参阅此答案。

2.缓存本地引用
作为本机函数的第二个参数接收的thiz引用是本地引用,调用JNI函数返回的大多数jobjects也是本地引用
本地引用只能“从最初传递给它的线程中”使用,并且在显式调用DeleteLocalRef()之前有效,或者更常见的是,在从本机方法返回之前有效

如果要从另一个线程使用该对象,则需要从本地引用创建全局引用:

m_globalObject = NewGlobalRef(thiz);

当您不再需要在本机代码中的任何位置使用全局引用时,请记住删除该引用(DeleteGlobalRef(m_globalObject))。否则可能会导致内存泄漏。

 类似资料:
  • 问题内容: 因此,我正在编写一个使用大型c 库的Android应用。我可以正常工作,以便Java应用程序可以调用c 委托方法,但是我发现自己希望自己可以将来自c 的消息记录到Android日志中。从Java上这很容易,但是我不知道如何从c 调用Java方法。我的搜索找到了从c 打开jvm的方法,这根本不是我想要做的。理想情况下,我想将日志方法指针传递给c ,然后可以在需要时使用它。当然,Java不

  • 所以我希望fxml文件中的这段代码实际上会调用sceneHandeler中的一个名为setBackground的方法,但它给了我一个错误:

  • 我正在制作一个库应用程序,该应用程序使用谷歌断路器检测android中的本机崩溃。每当我的主端发生本机崩溃时,断路器都会调用以下回调。从这个回调中,我需要使用JNI在java类中调用一个静态val方法。 这是我的java方法: 在Android5.0之前,这一功能一直运行良好。但在Lollipop中,我无法调用我的java方法,因为我无法在Logcat控制台上看到“内部句柄异常”日志。 以下是我在

  • 问题内容: 对于连接到服务器的每个客户端,我都会生成一个新线程,如下所示: 现在,我知道可以使用以下代码关闭 所有 线程: 但是,如何从关闭线程 内 该线程? 问题答案: 启动线程时,它开始执行您提供的功能(如果要扩展,该功能将为)。要结束线程,只需从该函数返回即可。 根据这个,你也可以打电话,这将抛出一个异常,将安静地结束线程。

  • 我的C代码无法找到Java中的公共静态函数调用。它成功地找到了类,没有错误。 我试图将结果返回给回调方法。“5”稍后将被更复杂的内容取代。 我在StackOverflow上似乎也有类似的问题,但是到目前为止没有任何变化似乎有所帮助。也许我有逻辑错误? 我的JNI(更新#2): 此代码包含在此函数中调用的方法中: 我的Java(更新#1): 签名检查: javap-s-pcecutils 公共静态响

  • 因此,有人知道如何杀死一个线程,同时它调用任何JNI函数而不使用while循环。