r16 - Mantener una referencia global al entorno JNIEnv.
ndk r13 (1)
Estoy almacenando JNIEnv
en un global para poder llamar a métodos de Java estáticos más adelante. Pero no es necesario almacenar un puntero global al JNIEnv
, tal como lo haríamos con cualquier otro objeto Java, o es un caso especial que no requiere esto.
JNIEnv* globalEnvPointer;
[JNICALL etc] void init(JNIENv* env, [etc])
{
//required?
globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env);
//or is this OK?
globalEnvPointer = env;
}
Editar
Aquí estoy un poco tonto, todos los métodos que usarán globalEnvPointer
se invocan dentro de mi init porque my init
es en realidad el método main
mi programa c
, que no volverá hasta el final del programa. Tampoco estoy usando otros hilos en el programa c Creo que esto simplifica la respuesta.
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
}
No puede JNIEnv
puntero JNIEnv
caché. Lea sobre esto here :
El puntero de la interfaz JNI (JNIEnv) solo es válido en el hilo actual. Si otro subproceso necesita acceder a la VM de Java, primero debe llamar a AttachCurrentThread () para adjuntarse a la VM y obtener un puntero de interfaz JNI. Una vez conectado a la máquina virtual, un subproceso nativo funciona igual que un subproceso Java normal que se ejecuta dentro de un método nativo. El subproceso nativo permanece adjunto a la máquina virtual hasta que llama a DetachCurrentThread () para separarse.
Lo que puedes hacer es JavaVM
puntero de JavaVM
en caché.
static JavaVM *jvm;
[JNICALL etc] void init(JNIENv* env, [etc])
{
jint rs = (*env)->GetJavaVM(env, &jvm);
assert (rs == JNI_OK);
}
Y luego, cuando sea necesario, a continuación, puntero JNIEnv
desde un contexto donde no se le da hacer esto:
void someCallback() {
JNIEnv *env;
jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
assert (rs == JNI_OK);
// Use the env pointer...
}
Pero cada vez que se llama a un método nativo de Java, se proporciona el puntero env a usar:
JNIEXPORT jint JNICALL Java_package_Class_method(JNIEnv *env, jobject obj) {
// just use the env pointer as is.
}