Linux线程通过JNI回调JAVA函数
最近做的一个小工程需要用到回调函数,由linux层回调到java层,调试的时候会遇到一些问题,免得忘记,在这里记录一下:
JNI的各种数据类型和数据结构我就不详细介绍了,简单说一下
JavaVM *m_jvm; java虚拟机,这个变量可以在不同的线程里面使用,获取的方法也有很多,可以通过env获取,也可以通过JNI_OnLoad函数来获取
JNIEnv *g_env; 这个是一个线程的相关变量,这里注意的是一个线程的,对于每个线程来说是唯一的,不能在不同的线程里面使用同一个env;
jobject g_obj; 因为java层的代码,native的接口和主activity不是放在同一个class里面,因此把主activity的obj传下来的,方便在JNI层更快的寻找到activity的class
jclass g_class; 为之前的g_obj里面的类对象
int flagthread = 0; 因为特殊原因,我的代码里面的第一个线程为UI线程,之后的线程由底层创建,因为设置一个flag来过滤第一个线程,方便之后的attach和detach
接下去就是上代码了
这是一个回调函数,给linux用的,上报状态的,在代码已经注明了必须attach,不然会报以下错误
E/dalvikvm( 2068): JNI ERROR: non-VM thread making JNI calls
E/dalvikvm( 2068): VM aborting
F/libc ( 2068): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 2125 (id.wifimiracast)
其实也很好理解,因为大家注意到我的接口并不是标准的JNI接口,这个接口是我自己创建供linux层回调的,一般标准的JNI接口,是直接供java层使用的,那时候的多线程attach其实是attach到UI线程上的,但在linux里面创建了一个线程去回调这个状态函数的时候,并没有涉及到UI线程,所以是到了JNI层的话,必须也得要有一个线程去处理这个回调,下面的就好理解了,JNI线程去回调java的时候,java也必须要有一个线程去处理,下面会讲到。
在代码里面可以看到我调用的是statebroadcast这个回调函数
这里必须要用handler去处理,不然会报如下错误
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.(Handler.java:121)
at com.cao.android.demos.handles.HandleTestActivity$MyThread$1.(HandleTestActivity.java:86)
at com.cao.android.demos.handles.HandleTestActivity$MyThread.run(HandleTestActivity.java:86)
这样从linux线程通过JNI调用到JAVA的函数就完全可以啦,第一次作记录,如果 有错误,欢迎斧正!