簡體   English   中英

在匿名類中使用方法參數會導致SIGSEGV

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM