我正在编写具有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拒绝打印变量,在当前上下文中说“无符号” * “。
请帮我解决这个问题。
答案 0 :(得分:0)
我认为你没有正确使用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
答案 1 :(得分:0)
最后我自己解决了问题。问题是,当我们从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完成之后,在SwigDirector_NativeLayerDelegate::OnMessage
中破坏了本机Message对象,并且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);
}