2012-09-14 10 views
27

Przechwytywam JNIEnv w globalnym, więc mogę nazwać statyczne metody java później. Ale czy nie jest konieczne zapisywanie globalnego wskaźnika do JNIEnv, w jaki sposób można by to zrobić z jakimkolwiek innym obiektem java, czy też jest to specjalny przypadek, który tego nie wymaga.Utrzymywanie globalnego odniesienia do środowiska JNIEnv

JNIEnv* globalEnvPointer; 

[JNICALL etc] void init(JNIENv* env, [etc]) 
{ 
    //required? 
    globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env); 
    //or is this OK? 
    globalEnvPointer = env; 
} 

Edit

mam bing nieco głupi tutaj, wszystkie metody, które wykorzystują globalEnvPointer, są wywoływane w moim init, ponieważ mój init jest rzeczywiście main metoda mojego c programu, który wygrał” t powrót do końca programu. Używam również żadnych innych wątków w programie c. Myślę, że to upraszcza odpowiedź. Nie można buforować wskaźnika

Odpowiedz

41

. Przeczytaj o tym here:

Wskaźnik interfejsu JNI (JNIEnv) jest ważny tylko w bieżącym wątku. Jeśli inny wątek musi uzyskać dostęp do maszyny wirtualnej Java, musi najpierw wywołać AttachCurrentThread(), aby dołączyć się do maszyny wirtualnej i uzyskać wskaźnik interfejsu JNI. Po podłączeniu do maszyny wirtualnej natywny wątek działa tak jak zwykły wątek Java działający w natywnej metodzie. Natywny wątek pozostaje podłączony do maszyny wirtualnej, dopóki nie wywoła funkcji DetachCurrentThread(), aby się odłączyć.

Zamiast tego można buforować wskaźnik JavaVM.

static JavaVM *jvm; 

[JNICALL etc] void init(JNIENv* env, [etc]) 
{ 
    jint rs = (*env)->GetJavaVM(env, &jvm); 
    assert (rs == JNI_OK); 
} 

I wtedy, kiedy trzeba wtedy JNIEnv wskaźnik od kontekstu, w którym nie jest podany to zrobisz:

void someCallback() { 
    JNIEnv *env; 
    jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL); 
    assert (rs == JNI_OK); 
    // Use the env pointer... 
} 

Ale kiedy zadzwonisz natywną metodę z Java wskaźnik env do użycia jest podana :

JNIEXPORT jint JNICALL Java_package_Class_method(JNIEnv *env, jobject obj) { 
    // just use the env pointer as is. 
} 
+0

Wszystko jedno, czy to ma znaczenie? tzn. mój 'init' jest wywoływany w tym samym wątku, który później wywoła statyczne metody java. – weston

+0

Zawsze używaj wskaźnika 'JNIEnv', który wchodzi w funkcję C. Jak w moim ostatnim przykładzie. – maba

+0

Proszę zobaczyć moją edycję, w twoim przykładzie, jeśli 'Java_package_Class_method' nazywa się' someCallback', nie musiałbyś iść przez 'JavaVM', prawda? W efekcie robię to, używając globalnej zamiast przekazywać ją do 'someCallback'. – weston

Powiązane problemy