java - una - JNI invocando métodos estáticos. ¿Es el objeto de clase necesario?
public static java (1)
Comencé a usar JNI para invocar métodos java estáticos de C ++. Específicamente, después de obtener un jclass (usando FindClass) y un jmethodID (usando GetStaticMethodID), procedí a llamar a la serie de rutinas CallStatic * MethodA. Resulta que todas estas rutinas toman un jclass como primer parámetro. Comencé a preguntarme por qué se necesita el objeto de clase: dado que toda la información se proporcionó en GetStaticMethodID, el objeto de clase parece innecesario para que la JVM realice el trabajo. Luego intenté llamar a estas rutinas mientras pasaba NULL para el primer parámetro, y la invocación tuvo éxito.
Mi pregunta: ¿Es seguro llamar a estos métodos con un objeto de clase NULL?
El incentivo es: si es legal, no tendré que almacenar en caché el objeto de clase para llamadas posteriores a los métodos estáticos (mientras recuerdo llamar a NewGlobalRef ...). El almacenamiento en caché del jmethodID sería suficiente.
No, no es absolutamente seguro llamar a dicha función estática con un puntero de clase nulo (o inválido).
Su práctica puede tener éxito, por ejemplo, si su método estático no se refiere a ningún otro miembro estático de la clase. Sin embargo, si su método Java estático se refiere a cualquier otro miembro estático, su JVM necesitará el puntero de clase válido.
Ejemplo:
Toma esta simple demo de Java MyTest.java
:
public class MyTest {
public static void mymain() {
System.out.println("Hello, World in java from mymain");
System.out.println(magic_counter); // this will cause a segfault if
} // class pointer is null
private static int magic_counter=777;
}
Y llámalo con el siguiente fragmento JNI C ++
... // JVM already loaded and initialised
jclass cls2 = env->FindClass("MyTest");
if(cls2 == nullptr) {
cerr << "ERROR: class not found !";
}
else {
cout << "Class MyTest found" << endl;
jmethodID mid = env->GetStaticMethodID(cls2, "mymain", "()V");
if(mid == nullptr)
cerr << "ERROR: method void mymain() not found !" << endl;
else {
env->CallStaticVoidMethod(cls2, mid);
cout << endl;
}
}
Llamar a GetStaticMethodID(nullptr, "mymain", "()V");
fallaría. Porque cuando mymain()
ejecuta, intentará acceder a la variable estática magic_number
. La JVM usará el puntero de clase que ha proporcionado y asumirá que es un puntero de vaild devuelto por una clase cargada. Pero como es nulo, el sistema segfault.