2012-10-04 21 views
14

¿Hay alguna manera de que pueda saber el nombre de la clase que llamó a un método en el código JNI C? Puedo obtener una referencia a la clase mediante la siguiente declaración:¿Puedo saber el nombre de la clase que llama a un método JNI C?

jclass cls = (*env)->GetObjectClass(env,obj); 

pero ¿hay alguna manera de saber el nombre de la clase? .

Respuesta

35

Este código le dará el nombre de la clase llamada:

jclass cls = env->GetObjectClass(obj); 

// First get the class object 
jmethodID mid = env->GetMethodID(cls, "getClass", "()Ljava/lang/Class;"); 
jobject clsObj = env->CallObjectMethod(obj, mid); 

// Now get the class object's class descriptor 
cls = env->GetObjectClass(clsObj); 

// Find the getName() method on the class object 
mid = env->GetMethodID(cls, "getName", "()Ljava/lang/String;"); 

// Call the getName() to get a jstring object back 
jstring strObj = (jstring)env->CallObjectMethod(clsObj, mid); 

// Now get the c string from the java jstring object 
const char* str = env->GetStringUTFChars(strObj, NULL); 

// Print the class name 
printf("\nCalling class is: %s\n", str); 

// Release the memory pinned char array 
env->ReleaseStringUTFChars(strObj, str); 

Tenga en cuenta que no he tomado ninguna acción para comprobar si hay errores. Esto es solo un pequeño fragmento de código que describe cómo se podría hacer.


alternativa usted puede hacer esto en lugar de utilizar el GetStringUTFChars/ReleaseStringUTFChars:

// Make sure that the buffer is large enough 
char str[128]; 
jint strlen = env->GetStringUTFLength(strObj); 
env->GetStringUTFRegion(strObj, 0, strlen, str); 
printf("\nCalling class is: %s\n", str); 

No hay necesidad de liberar ya que la cadena se copia en memoria intermedia local.

+1

Creo que no debería usar strlen como nombre de variable ya que es una función C estándar existente. –

+0

En mi experiencia, en realidad no necesita los pasos en "Primero obtenga el objeto de la clase"; 'clsObj' y' cls' son funcionalmente equivalentes. – shawkinaw

+0

El código de ejemplo muestra referencias locales con fugas ocultas si se usan "tal cual". Todas las referencias de jobject y jclass deben ser eliminadas. Además, esta es una mala práctica: jclass cls = env-> GetObjectClass (obj); ... cls = env-> GetObjectClass (clsObj); Sin liberar la referencia anterior almacenada en cls. –

-3

Solo invoque getName() en el jclass, también a través de JNI.

+0

quieres decir '((* env) -> GetObjectClass (env, obj)) -> getName()'? Quiero imprimir el nombre de la clase (que invocó el método) desde el código jni c –

+1

Me sale un error cuando hago lo anterior o 'jclass-> getName()' –

+2

FYI - en términos generales, cuando describes lo que Hecho, y qué mensajes de error, etc. le impiden tener éxito, obtendrá una mejor ayuda. La respuesta de EJP es correcta. Sin saber qué error está recibiendo, no podemos comenzar a comentar sobre lo que no funciona. Recuerde que getName() va a devolver un jstring ... –

7

En mi caso, no he tenido el objetivo de obtener la clase. En cambio, quería obtener el nombre de una clase determinada, en función de su firma.

Por lo tanto, esto funcionó para mí. Espero que pueda ayudar:

// Find the class by its JNI signature 
jclass cls = env->FindClass(expectedType); 

// Get the class object's class descriptor 
jclass clsClazz = env->GetObjectClass(cls); 

// Find the getSimpleName() method in the class object 
jmethodID methodId = env->GetMethodID(clsClazz, "getSimpleName", "()Ljava/lang/String;"); 
jstring className = (jstring) env->CallObjectMethod(cls, methodId); 

// And finally, don't forget to release the JNI objects after usage!!!! 
env->DeleteLocalRef(clsClazz); 
env->DeleteLocalRef(cls); 
Cuestiones relacionadas