2011-09-19 99 views
1

我需要通過JNI接口在我的Java對象和外部OCaml程序之間傳輸數據,但我有麻煩來訪問本機代碼中的對象字段。運行JNI本機代碼時JRE SIGSEGV

在Java方面,我有幾個字段類:

public class GPSState { 

     int fix; 
     double course; 
     double hmsl; 
     ... 
} 

我傳遞一個對象jstateGPSState級到C部分,在這裏我想設置其字段通過外部程序提供相應的值被保存在本地結構state

jclass cls; 
jfieldID fid; 

cls = (*env)->GetObjectClass(env, jstate); 

fid = (*env)->GetFieldID(env, cls, "fix", "I"); 
(*env)->SetIntField(env, cls, fid, state.fix); 

fid = (*env)->GetFieldID(env, cls, "course", "D"); 
(*env)->SetDoubleField(env, cls, fid, state.course); 

fid = (*env)->GetFieldID(env, cls, "hmsl", "D"); 
(*env)->SetDoubleField(env, cls, fid, state.hmsl); 

... 

從調試打印我學到了類表被成功定位和fixcourse字段被正確識別和設置。但是,SetDoubleField呼籲對course領域,這是一個調試打印確認馬上打電話線以下執行後,我總是得到SIGSEGV致命錯誤,當我嘗試訪問任何其他領域:

# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# SIGSEGV (0xb) at pc=0x01109720, pid=11665, tid=3079347056 
# 

後來我有發現,當我將操縱course字段的代碼移動到設置字段的C函數的最後時,錯誤消失並且所有字段都按預期設置,沒有任何問題。

我試着用另一個JRE實現運行另一臺機器上的代碼,但結果是一樣的,除了在設置第一個fix字段後發生的錯誤(將代碼的相應位移動到功能「再次解決」了這個問題)。

現在,我知道我不知何故搞亂了記憶,但我無法弄清楚在哪裏以及如何。我遵循JNI程序員指南中的字段和方法章節來檢查可能的錯誤,但在我看來,我完成了本書的所有工作。有人更有經驗會如此善良,並指出問題出在哪裏?

回答

2
(*env)->SetIntField(env, cls, fid, state.fix); 

這看起來不對。您正試圖設置一個對象實例字段,但是您要傳遞cls而不是jstate作爲要訪問的對象。您應該改用以下內容:

(*env)->SetIntField(env, jstate, fid, state.fix); 

讓您的其他Set<type>Field調用相應的改變。

+0

該死的,我怎麼會想念那個?謝謝,斯圖爾特! – petok