2012-04-20 24 views
5

Başka bir yürütülebilir dosyadan arama yedeklerini alan bir cpp dosyasından Java sınıfı yöntemlerini aramak istiyorum. Android NDK içinde iş parçacıkları arasında bir JavaVM * paylaşma

Bu amaca ulaşmak için

, doğrudan JNI'yı yöntem çağrıları alır .Cpp dosyasında robot :: AndroidRuntime :: getJavaVM() yöntemini kullanarak bir JavaVM işaretçiyi geri var. Ben şöyle Java yöntemleri gerekli çağrı nihai .cpp dosyasına yapıcı üzerinden bu JavaVM işaretçisi paylaşıyorum:

/* 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");** 

Ancak, ben bu kodu çalıştırarak bir SIGSEGV arızayı olsun. Bu konuda herhangi bir yardım takdir edilecektir http://java.sun.com/docs/books/jni/html/other.html#26206

:

JNI'yı belgelerine göre bu keyfi bağlamlarda JNIEnv almaya yönelik bir yol olarak görünmektedir.

Selamlar, Neeraj

+0

Nedir android :: AndroidRuntime :: getJavaVM)? Bu NDK public API işlevi değil. Belgesiz bir şey kullanıyorsunuz. NDV'de JavaVM * almak için, paylaşılan kitaplığınız yüklendiğinde otomatik olarak çağrılan JNI_OnLoad global işlevini uygulamanız gerekir. –

+0

Yanıtınız için teşekkürler .. http://android.wooyd.org/JNIExample/#NWD1sCYeT-J - bu belge, android :: AndroidRuntime :: registerNativeMethods() yönteminin kullanıldığı JNI_OnLoad için çok iyi bir giriş sağlar. Android :: AndroidRuntime'in belgelenmediğinden emin misiniz? – Neeraj

+0

Evet, normal kullanıcı NDK kodunda belgesiz özellik. JNI belgelerini (Sun) okuyun ve diğer yasal ve belgelendirilmiş API için NDK klasörünüzdeki docs/STABLE-APIS.html dosyasını kontrol edin. –

cevap

4
Eğer ekleme olmadan bir JNIEnv veya JavaVM başvuru kullanmaya çalışırsanız yeni dizisindeki bir segment hataya engel ETMEYECEKTIR

Küresel referanslar VM'ye iş parçacığı. Mārtiņš Možeiko, ilk kez doğru bir şekilde yapıyordu, yaptığınız şeyle ilgili yanlış bir şey olduğunu ima ederek yanılıyor.

Kaldırma, sadece nasıl kullanacağınızı öğrenin. O adam ne hakkında konuştuğunu bilmez, eğer jni.h'de olursa olsun hiçbir yere gitmediğinden emin olabilirsiniz. Belgelenmemiş olmasının nedeni muhtemelen gülünç bir şekilde kendini açıklayıcı olması. GlobalReference nesneleri veya herhangi bir şey oluşturmanıza gerek yok, sadece şu gibi bir şey yapın:

#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(); 
} 
+0

Jni.h'den bir şey kullanmanın yanlış mı, izin verilmediğini nereden söyledim? –

+1

"Bu NDK public API işlevi değil. Belgesiz bir şey kullanıyorsunuz.NDK'da JavaVM * almak için, paylaşılan kütüphaneniz yüklendiğinde otomatik olarak çağrılan JNI_OnLoad global işlevini uygulamanız gerekir. "Söylemekten ötürü özür dilerim ama bu tüm ifade doğru değil. –

+0

Ve bu doğru - android :: AndroidRuntime :: getJavaVM' jni.h'de bir genel işlev veya yöntem değildir. jni.h (global JNI_OnLoad veya JavaVM veya JNIEnv gibi) işlevlerini veya yöntemlerini kullanmanın izin verilmediğini asla söylemedim. o jni.h ile düzgün bir şekilde onu kullanarak değil nasıl o ** ile uygun şekilde yapıyor olabilir android :: AndroidRuntime :: getJavaVM ** jni.h değil android internals fonksiyonu? –

0

sorunu çözüldü. Bölümleme hatası, paylaşılan jvm işaretçisinden alınan JNIEnv nesnesinden jclass nesnesini alamadığım için oldu.

Global referans jclass nesnesini jvm ile birlikte yaydım ve sorun çözüldü. Yardımlarınız Mārtiņš Možeiko! ..

Selamlar, Neeraj için

Teşekkür

İlgili konular