Я использую следующий код, чтобы попытаться получить класс RWException (который расширяет Exception) в Java, чтобы я мог вызвать метод «getCode ()», чтобы получить код ошибки (int) и правильно обработать ошибку. Я просмотрел документы JNI и создал следующий код … проблема в том, что я получаю исключение AccessViolation, когда пытаюсь вызвать метод getCode () без параметров. Я получил правильный дескриптор для класса и идентификатор метода, который я ищу.
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);
}
Этот код дает мне исключение при отладке в VS.NET со следующей информацией:
Попытка чтения или записи в защищенную память
ОБНОВИТЬ
Вот метод Java, который я хочу вызвать через код JNI выше:
public int getCode() {
return code;
}
Оба объекта, mvclass и mid, созданы должным образом и должны функционировать, если я что-то не упустил.
ОБНОВЛЕНИЕ 2
Если я запускаю следующий код, метод toString () работает с использованием той же концепции:
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;
}
Итак, метод toString () возвращает полное имя класса объекта, и это правильный объект RWException. Метод, описанный в первом обновлении getCode (), является общедоступным и т. Д., Поэтому не уверен, почему он выдает ошибку нарушения доступа к памяти.
// 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);
Ух ты.
И компилятор не жалуется на это, потому что каждый jclass
это jobject
, как jstring
,
Единственная возможная проблема, которую я вижу в вашем коде, это то, что вы вызываете метод, пока исключение все еще распространяется. envLoc->ExceptionOccurred()
дает вам объект исключения, но вы все равно должны его поймать envLoc->ExceptionClear()
,
У вас нет проверки ошибок в этом коде. Вам необходимо проверить результат каждой операции JNI: GetObjectClass (), GetMethodID (), CallXXXMethod () … Например, вы предполагаете, что у класса есть метод getCode (), и вызываете его, не проверяя его.