Einen globalen Verweis auf die JNIEnv-Umgebung beibehalten

Lesezeit: 3 Minuten

Benutzeravatar von Weston
Westen

Ich speichere ab JNIEnv in einem globalen, damit ich später statische Java-Methoden aufrufen kann. Aber ist es notwendig, einen globalen Zeiger auf die zu speichern JNIEnvwie man es mit jedem anderen Java-Objekt tun würde, oder ist es ein Sonderfall, der dies nicht erfordert.

JNIEnv* globalEnvPointer;

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

Bearbeiten

Ich bin hier ein bisschen dumm, alle Methoden, die verwendet werden globalEnvPointerwerden in meiner Init aufgerufen, weil meine init ist eigentlich mein c Programm main -Methode, die erst am Ende des Programms zurückkehrt. Ich verwende auch keine anderen Threads im C-Programm. Ich denke, das vereinfacht die Antwort.

JNIEnv* globalEnvPointer;

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

void someMethod()
{
   //use globalEnvPointer here
}

Benutzeravatar von maba
Mama

Sie können die nicht zwischenspeichern JNIEnv Zeiger. Lese darüber hier:

Der JNI-Schnittstellenzeiger (JNIEnv) ist nur im aktuellen Thread gültig. Sollte ein anderer Thread auf die Java VM zugreifen müssen, muss er zuerst AttachCurrentThread() aufrufen, um sich selbst an die VM anzuhängen und einen JNI-Schnittstellenzeiger zu erhalten. Einmal mit der VM verbunden, funktioniert ein nativer Thread genau wie ein gewöhnlicher Java-Thread, der innerhalb einer nativen Methode ausgeführt wird. Der native Thread bleibt mit der VM verbunden, bis er DetachCurrentThread() aufruft, um sich selbst zu trennen.

Was Sie tun können, ist, die Datei zwischenzuspeichern JavaVM Zeiger statt.

static JavaVM *jvm;

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

Und dann, wann immer Sie es brauchen JNIEnv Zeiger aus einem Kontext, in dem es nicht gegeben ist, tun Sie dies:

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

Aber immer wenn Sie eine native Methode von Java aufrufen, wird der zu verwendende env-Zeiger angegeben:

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

  • Es ist alles ein Thread, macht das einen Unterschied? dh meine init wird im selben Thread aufgerufen, der später die statischen Java-Methoden aufruft.

    – Westen

    14. September 2012 um 9:27 Uhr

  • Könntest du, aber ist das nicht hässlich? Das Speichern temporärer Daten in globalen Variablen, die von anderen Methoden verwendet werden sollen, ist in meinen Augen ein Anti-Pattern.

    – Mama

    14. September 2012 um 9:49 Uhr

  • Ja, ich stimme zu, aber ich versuche, einen riesigen zu nehmen c Source-Basis und über 100 Assembler-Methoden in Java umschreiben (wie z someCallback). Wir sprechen von einigen tausend Orten, an denen Anrufungen durchgeführt werden. Außerdem sollte dieselbe Quellbasis immer noch für ihr ursprüngliches Ziel kompiliert werden, also bestanden JNIEnv herum ist eigentlich die hässliche Lösung. Danke für die ganzen Tipps, ich werde sie berücksichtigen, wenn ich Threads verwenden muss.

    – Westen

    14. September 2012 um 10:25 Uhr


  • Ich würde keine eigene Init-Funktion erstellen, wenn es bereits JNI_OnLoad gibt, das die JavaVM übergibt.

    – DanielB

    17. Mai 2017 um 12:58 Uhr

  • @maba: Das OP benötigt möglicherweise eine separate Init-Funktion, aber vielleicht weiß er auch überhaupt nichts über die Existenz von JNI_OnLoad. Es erweitert nur die Antwort. Es ist nicht als Kritik gemeint, sondern nur als freundlicher kleiner Erweiterungshinweis. Ich schreibe keine eigene Antwort, weil ich denke, dass Ihre Antwort bereits gut ist und Sie die Punkte bekommen sollten. Denken Sie jedoch auch daran, dass andere Personen Ihre Antwort lesen, nicht nur das OP, und es gibt erfahrene und unerfahrene Personen unter ihnen.

    – DanielB

    1. September 2017 um 17:16 Uhr

1395100cookie-checkEinen globalen Verweis auf die JNIEnv-Umgebung beibehalten

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy