2012-09-07 41 views
1

我正在使用以下代碼嘗試在java中獲取類RWException(它擴展了Exception),以便我可以調用方法「getCode()」來檢索一個錯誤代碼(int)並正確處理錯誤。我通過JNI文檔並創建了以下代碼...問題是,當我試圖調用無參數方法getCode()時,我得到了AccessViolation異常。我得到了一個有效的類和我正在尋找的方法ID的句柄。JNI獲取異常信息 - 嘗試讀取或寫入受保護的內存

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); 
} 

此代碼給了我一個異常而調試inVS.NET /以下信息寬:

試圖讀取或寫入保護內存

UPDATE 這裏是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()中概述的方法是公共的,等等......所以不知道爲什麼它會導致內存訪問衝突錯誤。

+0

異常很簡單,嘗試抓住和完成。 –

+1

在java端發生異常......然後拋出RWException類型的異常,然後嘗試通過ExceptionOccurred()方法嘗試並捕獲該異常。然後,需要通過getCode()方法從RWException對象獲取代碼 - 在java中它會沿着int代碼行= oRWexception.getCode(); – bbqchickenrobot

+0

是的,發生異常是因爲它沒有正確捕獲 –

回答

2
// 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); 

哦,哇。

而編譯器不會抱怨這個,因爲每個jclassjobject,就像jstring

+0

和BOOM!你是人!像魅力一樣工作。是的,編譯器完全沒有抱怨。事實上,這是給我的方法身份證的一切 - 細節......細節......大聲笑。非常感謝我的「主」人哈哈 – bbqchickenrobot

2

我可以在代碼中看到的唯一可能的問題是,當異常仍在傳播時,您正在調用方法。 envLoc->ExceptionOccurred()給你的異常對象,但你仍然必須實際趕上它與envLoc->ExceptionClear()

+0

Ur right ...我將方法調用從getCode切換到toString,上面的代碼正常工作...不知道那是什麼意思... – bbqchickenrobot

+0

如果爲'getCodeMeth'添加空檢查會發生什麼? –

+0

它通過,因爲它* *不*空...所以不知道爲什麼它炸燬。確實很奇怪... – bbqchickenrobot

1

您在此代碼中沒有檢查錯誤。您需要檢查每個JNI操作的結果:GetObjectClass(),GetMethodID(),CallXXXMethod()...例如,您假定該類有一個getCode()方法,並且調用它而不檢查該方法。

+0

我已經通過IDE調試器檢查 - GetObjectClass(),GetMethodID()的所有返回值都是* not * null,如原始帖子中所述... CallIntMethod(xxx,xxx)甚至不會返回 - 它帶有Access Violation異常的JNI.h調用中爆炸。另外,envLoc也是有效的。 – bbqchickenrobot

+0

@bbqchickenrobot:即使如此,這是一個很好的建議。 – PJTraill

相關問題