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