5

別の実行可能ファイルからコールバックを受け取る cpp ファイルから Java クラス メソッドを呼び出したいと考えています。

これを実現するために、 JNI メソッド呼び出しを直接受け取る .cpp ファイルの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 を取得する適切な方法のようです: http://java.sun.com/docs/books/jni/html/other.html#26206

この点で何か助けていただければ幸いです。

よろしく、 ニーラジ

4

2 に答える 2

2

スレッドをVMに接続せずに、JNIEnvまたはJavaVM参照を使用しようとすると、グローバル参照によって新しいスレッドのセグメンテーション違反が防止されません。あなたは最初はそれをきちんとやっていたのですが、MārtiņšMožeikoはあなたがしていることに何か問題があったと誤解しています。

削除せず、使い方を学んでください。その男は彼が何について話しているのかわかりません。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();
}
于 2012-12-07T23:21:42.490 に答える
0

問題を解決しました。セグメンテーション違反は、共有 jvm ポインターから取得した JNIEnv オブジェクトから jclass オブジェクトを取得できなかったためです。

jvmとともにグローバル参照jclassオブジェクトを伝播し、問題は解決しました。

ご協力ありがとうございました Mārtiņš Možeiko!..

よろしく、 ニーラジ

于 2012-04-23T07:07:50.990 に答える