[英]Using method parameters in anonymous class causes SIGSEGV
我正在編寫具有Java和本機部分的Android應用程序。 Java部分將消息發送到本機部分並接收返回的答案。 本機部分在單獨的線程上完成所有工作,當它返回答案時,我想處理主線程上的答案。 這是我擴展的Application類的一部分:
@Override
public void OnMessage(final Message msg, final long answerTo) {
Log.i(TAG, msg.ToStr()); // OK
handler.post(new Runnable() {
@Override
public void run() {
Log.i(TAG, msg.ToStr()); // Fatal signal 11 (SIGSEGV)
// at 0x74616862 (code=1), thread 13255
}
});
}
本機代碼在其線程上調用OnMessage方法,並嘗試通過Handler將其傳遞給UI線程。 當我嘗試在UI線程中使用msg的任何方法時,我的程序因SEGSEGV失敗。
重要的事實是Message類是C ++ Message類的包裝器。 包裝是由SWIG生成的。
我試圖在GDB中調試它,GDB甚至向我顯示了堆棧跟蹤,該跟蹤以本機Message.toStr方法結尾。 但是gdb拒絕打印變量,說“在當前上下文中沒有符號“ * ”。
請幫我解決這個問題。
我認為您沒有為要執行的操作正確使用Handler(跨線程復制對象)。 在此處查看博客文章:
http://techtej.blogspot.com/2011/02/android-passing-data-between-main.html
具體來說,是將消息發送到處理程序,如下所示:
Message msg = Message.obtain();
msg.obj = // Some Arbitrary object
mHandler.sendMessage(msg);
我不認為您執行此操作的方式會在線程之間執行Handler復制數據的魔力,因為它只是運行Runnable。
編輯:我很好奇,看看這是否是問題,所以即使不是,您也不能在評論中回復讓我知道結果嗎?
編輯2:所以看起來您的對象可能被存儲為JNI層中的本地引用。 不幸的是,這還不足以滿足您的目的,您可能需要使其成為全局引用。 只是要警惕這樣一個事實,如果您將其設置為全局引用,則必須在完成處理后以本機代碼自己將其刪除。
http://developer.android.com/training/articles/perf-jni.html#local_and_global_references
最后我自己解決了問題。 問題是,當我們從C ++到Java進行調用時,SWIG代理方法將指向其參數的指針傳遞給了Java端。 就像是:
void SwigDirector_NativeLayerDelegate::OnMessage(Message msg, Long answer_to) {
...
*((Message **)&jmsg) = &msg;
...
jenv->CallStaticVoidMethod(..., jmsg, ...);
...
}
在Java端,另一個代理方法收到了指針,並用Message類的Java表示將其包裝,並將其傳遞給Java方法OnMessage:
public static void SwigDirector_NativeLayerDelegate_OnMessage(
NativeLayerDelegate self, long msg, long answer_to) {
self.OnMessage(new Message(msg, false), answer_to);
// false parameter means that Message object isn't owner of 'msg' pointer, so it
// shouldn't free it on finalize.
}
OnMessage完成后,本機Message對象在SwigDirector_NativeLayerDelegate::OnMessage
被破壞,而Java Message對象保留了指向被破壞本機對象的指針。
解
我已經為Message對象編寫了自定義類型映射:
%typemap(directorin,descriptor="L$packagepath/$javaclassname;") Message
%{*((Message**)&$input) = new Message($1);%}
%typemap(javadirectorin,descriptor="L$packagepath/$javaclassname;") Message
%{new Message($1, true)%}
現在SwigDirector_NativeLayerDelegate :: OnMessage創建msg
副本,Java對象擁有它:
// Native
void SwigDirector_NativeLayerDelegate::OnMessage(Message msg, Long answer_to) {
...
*((Message**)&jmsg) = new Message(msg);
...
jenv->CallStaticVoidMethod(..., jmsg, ...);
...
}
// Java
public static void SwigDirector_NativeLayerDelegate_OnMessage(
NativeLayerDelegate self, long msg, long answer_to) {
self.OnMessage(new Message(msg, true), answer_to);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.