java - protegida - exception info system accessviolationexception
JNI Getting Exception Info-Intentó leer o escribir en la memoria protegida (3)
Estoy usando el siguiente código para tratar de obtener una clase RWException (que amplía Exception) en java para que pueda llamar a un método "getCode ()" para recuperar un código de error (int) y manejar el error correctamente. Revisé los documentos de JNI y creé el siguiente código ... el problema es que recibo una excepción de AccessViolation cuando intento llamar al método sin parámetros getCode (). Obtengo un identificador válido para la clase y el ID de método que estoy buscando.
jstring o = (jstring)envLoc->CallStaticObjectMethod(cls, mid, jstrUser, jstrPass, jstrGroup);
jthrowable exc = envLoc->ExceptionOccurred();
if (exc) {
// Get the class
jclass mvclass = env->GetObjectClass( exc );
// Get method ID for method
jmethodID mid = env->GetMethodID(mvclass, "getCode", "()I");
// Call the method
jint code = env->CallIntMethod(mvclass, mid);
}
Este código me da una excepción al depurar en VS.NET con la siguiente información:
Intento de leer o escribir en la memoria protegida
ACTUALIZAR Aquí está el método java que deseo invocar a través del código JNI arriba:
public int getCode() {
return code;
}
Ambos objetos, mvclass y mid, se crean correctamente y deben funcionar a menos que me falta algo.
ACTUALIZACIÓN 2
Si ejecuto el siguiente código, el método toString () funciona usando el mismo concepto:
jstring o = (jstring)envLoc->CallStaticObjectMethod(cls, mid, jstrUser, jstrPass, jstrGroup);
exc = envLoc->ExceptionOccurred();
if (exc) {
envLoc->ExceptionClear();
// Get the class
jclass exccls = envLoc->GetObjectClass(exc);
// Get method ID for methods
jmethodID getCodeMeth = envLoc->GetMethodID(exccls, "getCode", "()I");
jmethodID getMsgMeth = envLoc->GetMethodID(exccls, "toString", "()Ljava/lang/String;");
jstring obj = (jstring)envLoc->CallObjectMethod(exccls, getMsgMeth);
String^ toString = JStringToCliString(obj);
// this is where the access violation occurs
jint jcode = envLoc->CallIntMethod(exccls, getCodeMeth);
int code = jcode;
}
Entonces, el método toString () devuelve el nombre de clase completo del objeto y es el objeto RWException correcto. El método descrito en la primera actualización getCode () es público, etc. por lo que no estoy seguro de por qué da un error de violación de acceso a la memoria.
El único problema posible que puedo ver en su código es que está llamando a un método mientras una excepción todavía se está propagando. envLoc->ExceptionOccurred()
le proporciona el objeto de excepción pero todavía tiene que atraparlo con envLoc->ExceptionClear()
.
// exc is the exception object
exc = envLoc->ExceptionOccurred();
...
// exccls is the exception CLASS
jclass exccls = envLoc->GetObjectClass(exc);
jmethodID getCodeMeth = envLoc->GetMethodID(exccls, "getCode", "()I");
...
// CallIntMethod(jobject instance, jmethodID method)
jint jcode = envLoc->CallIntMethod(exccls, getCodeMeth);
// exccls is the CLASS, not the object
// so correct would be:
jint jcode = envLoc->CallIntMethod(exc, getCodeMeth);
Oh wow.
Y el compilador no se queja de esto porque cada jclass
es un jobject
, al igual que jstring
.
No tiene errores al verificar en este código. Debe verificar el resultado de cada operación JNI: GetObjectClass (), GetMethodID (), CallXXXMethod () ... Por ejemplo, usted está asumiendo que la clase tiene un método getCode () y lo llama sin verificarlo.