繁体   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