Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 在Android NDK中跨线程共享JavaVM*_Multithreading_Android Ndk_Java Native Interface - Fatal编程技术网

Multithreading 在Android NDK中跨线程共享JavaVM*

Multithreading 在Android NDK中跨线程共享JavaVM*,multithreading,android-ndk,java-native-interface,Multithreading,Android Ndk,Java Native Interface,我想从接收来自另一个可执行文件的回调的cpp文件调用Java类方法 为了实现这一点,我在.cpp文件中使用直接接收JNI方法调用的android::AndroidRuntime::getJavaVM()方法检索了一个JavaVM指针。我通过构造函数共享这个JavaVM指针,指向最终的.cpp文件,在该文件中我调用所需的Java方法,如下所示: /* All the required objects(JNIEnv*,jclass,jmethodID,etc) are appropriately d

我想从接收来自另一个可执行文件的回调的cpp文件调用Java类方法

为了实现这一点,我在.cpp文件中使用直接接收JNI方法调用的android::AndroidRuntime::getJavaVM()方法检索了一个JavaVM指针。我通过构造函数共享这个JavaVM指针,指向最终的.cpp文件,在该文件中我调用所需的Java方法,如下所示:

/* All the required objects(JNIEnv*,jclass,jmethodID,etc) are appropriately declared. */
**JNIEnv* env;
jvm->AttachCurrentThread(&env, NULL);
clazz = env->FindClass("com/skype/ref/NativeCodeCaller");
readFromAudioRecord = env->GetStaticMethodID(clazz, "readFromAudioRecord", "([B)I");
writeToAudioTrack = env->GetStaticMethodID(clazz, "writeToAudioTrack", "([B)I");** 
但是,运行此代码时出现了一个SIGSEGV错误

根据JNI文档,这似乎是在任意上下文中获得JNIEnv的适当方式:

在此方面的任何帮助都将不胜感激

问候,,
Neeraj解决了这个问题。分段错误是因为我无法从从共享jvm指针检索的JNIEnv对象检索jclass对象

我与jvm一起提出了一个全局引用jclass对象,问题就解决了

谢谢你的帮助,玛蒂·莫泽科

问候,,
如果您尝试使用JNIEnv或JavaVM引用而不将线程附加到VM,则Neeraj

全局引用将不会阻止新线程中出现分段错误。你第一次做得很好,玛蒂莫季科错误地暗示你所做的事情有问题

不要移除它,只是学习如何使用它。那家伙不知道他在说什么,如果是在jni.h你可以很肯定它不会去任何地方。它没有被记录的原因可能是因为它可笑地不言自明。您也不需要创建GlobalReference对象或任何东西,只需执行以下操作:

#include <jni.h>
#include <string.h>
#include <stdio.h>
#include <android/log.h>
#include <linux/threads.h>
#include <pthread.h>

#define  LOG_TAG    "[NDK]"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

static pthread_mutex_t thread_mutex;
static pthread_t thread;
static JNIEnv* jniENV;

void *threadLoop()
{
    int exiting;
    JavaVM* jvm;
    int gotVM = (*jniENV)->GetJavaVM(jniENV,&jvm);
    LOGI("Got JVM: %s", (gotVM ? "false" : "true") );
    jclass javaClass;
    jmethodID javaMethodId;
    int attached = (*jvm)->AttachCurrentThread(jvm, &jniENV,NULL);
    if(attached>0)
    {
        LOGE("Failed to attach thread to JavaVM");
        exiting = 1;
    }
    else{
        javaClass= (*jniENV)->FindClass(jniENV, "com/justinbuser/nativecore/NativeThread");
        javaMethodId= (*jniENV)->GetStaticMethodID(jniENV, javaClass, "javaMethodName", "()V");
    }
    while(!exiting)
    {
        pthread_mutex_lock(&thread_mutex);
        (*jniENV)->CallStaticVoidMethod(jniENV, javaClass, javaMethodId);
        pthread_mutex_unlock(&thread_mutex);
    }
    LOGE("Thread Loop Exiting");
    void* retval;
    pthread_exit(retval);
    return retval;
}

void start_thread(){
    if(thread < 1)
        {
            if(pthread_mutex_init(&thread_mutex, NULL) != 0)
            {
                LOGE( "Error initing mutex" );
            }
            if(pthread_create(&thread, NULL, threadLoop, NULL) == 0)
            {
                LOGI( "Started thread#: %d", thread);
                if(pthread_detach(thread)!=0)
                {
                    LOGE( "Error detaching thread" );
                }
            }
            else
            {
                LOGE( "Error starting thread" );
            }
        }
}

JNIEXPORT void JNICALL
Java_com_justinbuser_nativecore_NativeMethods_startThread(JNIEnv * env, jobject this){
    jniENV = env;
    start_thread();
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义日志标签“[NDK]”
#定义LOGI(…)\uuuuuAndroid\uLog\uPrint(android\uLog\uInfo、log\uTag、VA\uArgs\uuuu)
#定义LOGW(…)\uuuuuAndroid\uLog\uPrint(android\uLog\uWarn、log\uTag、VA\uArgs\uuuuu)
#定义日志(…)\uuuuuAndroid\uLog\uPrint(android\uLog\uError,log\uTag,\uuuU VA\uArgs\uuuuu)
静态pthread_mutex_t thread_mutex;
静态pthread\u t线程;
静态JNIEnv*JNIEnv;
void*threadLoop()
{
int退出;
JavaVM*jvm;
int-gotVM=(*jniENV)->GetJavaVM(jniENV和jvm);
LOGI(“获得JVM:%s”,(gotVM?false):“true”);
jclass-javaClass;
jmethodidejavamethodid;
int attached=(*jvm)->AttachCurrentThread(jvm,&jniENV,NULL);
如果(已附加>0)
{
LOGE(“未能将线程连接到JavaVM”);
退出=1;
}
否则{
javaClass=(*jniENV)->FindClass(jniENV,“com/justinbuser/nativecore/NativeThread”);
javaMethodId=(*jniENV)->GetStaticMethodID(jniENV,javaClass,“javaMethodName”,“()V”);
}
当(!退出)
{
pthread_mutex_lock(&thread_mutex);
(*jniENV)->CallStaticVoidMethod(jniENV,javaClass,javaMethodId);
pthread_mutex_unlock(&thread_mutex);
}
LOGE(“线程循环退出”);
作废*收回;
pthread_退出(retval);
返回返回;
}
无效开始线程(){
如果(螺纹<1)
{
if(pthread\u mutex\u init(&thread\u mutex,NULL)!=0)
{
LOGE(“启动互斥锁时出错”);
}
if(pthread_create(&thread,NULL,threadLoop,NULL)==0)
{
LOGI(“已启动线程:%d”,线程);
如果(pthread_detach(thread)!=0)
{
LOGE(“螺纹分离错误”);
}
}
其他的
{
LOGE(“错误启动线程”);
}
}
}
JNIEXPORT void JNICALL
Java_com_justinbuser_nativecore_NativeMethods_startThread(JNIEnv*env,jobject this){
jniENV=env;
启动_线程();
}

什么是android::AndroidRuntime::getJavaVM)?这不是NDK公共API函数。您正在使用未记录的内容。要在NDK中获取JavaVM*,您必须实现JNI_OnLoad全局函数,该函数在加载共享库时自动调用。感谢您的响应..-本文档非常好地介绍了JNI_OnLoad,其中使用了android::AndroidRuntime::registerNativeMethods()。你确定android::AndroidRuntime是非文档化的吗?是的,它是普通用户NDK代码中未文档化的功能。阅读JNI文档(来自Sun)并检查NDK文件夹中的docs/STABLE-API.html文件,以了解其他法律和文档化的API。该文档是关于NDK问世之前的Android编程的。请阅读第一节“重要通知”。再次感谢您指出这一点。我删除了对android::AndroidRuntime::getJavaVM()的调用,并使用JNI_onLoad来传播JavaVM*指针。但是,仍然会出现相同的SIGSEGV故障。有什么想法吗?我在哪里说过使用jni.h中的东西是错误的或不允许的?“这不是NDK公共API函数。您使用的是未记录的东西。要在NDK中获得JavaVM*,您必须实现jni_OnLoad全局函数,该函数在加载共享库时自动调用。”很抱歉这么说,但整个语句显然是不正确的。这是真的-
android::AndroidRuntime::getJavaVM
在jni.h中不是一个公共函数或方法。我从来没有说过不允许使用jni.h中的函数或方法(例如全局jni_OnLoad、JavaVM或JNIEnv)。但是你暗示我说了一些关于他没有正确使用jni.h函数的事情。他怎么能用android内部的android::AndroidRuntime::getJavaVM函数正确地完成它,而jni.h中没有这个函数?是的,它是jni.h中的一个公共函数,如果您费心仔细查看的话,我在上面的源代码中包括了一个具体如何使用它的示例。他所做的是正确的,你告诉他他错了,这就是我的反应。这是NDK r8d平台\android-14\arch arm\usr\include\jni.h的jni.h文件。请告诉我
android
AndroidRuntime
名称空间在哪里。