android multithread in c/c++ to call JNI
2014-01-02 15:06
288 查看
转载:请注明原地址: /article/10219771.html
android的c/c++调用java的代码
都是通过jni的。
但如果你在c/c++新建自己的线程,然后在线程上通过jni调用java的代码,那就麻烦来了。
找不到你需要调用的class。
怎么办?
Android里面有说明,http://developer.android.com/training/articles/perf-jni.html 。
造成这个原因是:
You can get into trouble if you create a thread yourself (perhaps by calling
Now the stack trace looks like this:
The topmost method is
thread, the JavaVM will start in the "system" class loader instead of the one associated with your application, so attempts to find app-specific classes will fail.
也就是说,当前java的VM的线程的CallStack是
JavaVM将使用系统的class loader而不是你的应用使用的class loader. 从而去找应用自身的类,将会失败。
android也给出了几个解决方案:
There are a few ways to work around this:
Do your
for later use. Any
with the function that called
use the correct class loader.
Pass an instance of the class into the functions that need it, by declaring your native method to take a Class argument and then passing
Cache a reference to the
directly. This requires some effort.
第一种方法就是通过在本来的java线程调用c/c++的时候,来获取相应的jclass,然后缓存起来。
一般做法就是在JNI_OnLoad方法处理。 这个是有局限的。如果你的类不多,这样处理还是可行的。
第二种方法,网上的例子比较多,就是在本来的java线程中调用自定义的native函数。从而在native中缓存此对象。然后在新建的线程里面通过此对象来获取相应的class。 这个方法和上面的类似。如果类过多,就需要多个此对象。
网上有此代码。不过有些地方描述不清楚。我这边总结一下:
Java的代码
void setJNIEnv();
在应用开始的地方,调用此方法,一般是Activity的onCreate。
在c/c++端native文件中:
JavaVM *g_jvm = NULL;
jobject g_obj = NULL;
JNIEXPORT void Java_YOURCLASS_setJNIEnv( JNIEnv* env, jobject obj)
{
(*env)->GetJavaVM(env,&g_jvm);
g_obj = (*env)->NewGlobalRef(env,obj);
}
这样就建立起了全局的object。
然后在你的c/c++的线程函数中:
in your thread fund:
JNIEnv* env = NULL;
if( g_jvm->AttachCurrentThread(&env,NULL) < 0)
{
/// your error process.
}
jclass cls = (*env)->GetObjectClass(env,g_obj);
if(cls == NULL)
{
///your error process.
}
///获取到jclass, 就可以调用此class的方法了。
/// GetMethodID 和 CallVoidMethod 等各种jni方法可以调用。 class参数将cls放入。
…….
在你的线程结束的地方:调用
g_jvm->DetachCurrentThread();
既:一个native线程,开始必须调用 AttachCurrentThread. 结束调用 DetachCurrentThread。
不建议多次调用 AttachCurrentThread / DetachCurrentThread。否则可能会造成虚拟机的内存泄漏问题。
因为调用 AttachCurrentThread 是java虚拟机要创建java端的线程与之对应。 这个开销大家自己去想吧。呵呵。因此,一个线程just call one time。
从上面的过程来看,它回避了 env->FindClass的问题。
哪有没有更好的方法呢?
差不多就是android的第三种方法,通过
这里写的过多了,新开第二篇来描述ClassLoader的方法。
android multithread in c/c++ to call JNI 的第二篇: /article/10219772.html
android的c/c++调用java的代码
都是通过jni的。
但如果你在c/c++新建自己的线程,然后在线程上通过jni调用java的代码,那就麻烦来了。
找不到你需要调用的class。
怎么办?
Android里面有说明,http://developer.android.com/training/articles/perf-jni.html 。
造成这个原因是:
You can get into trouble if you create a thread yourself (perhaps by calling
pthread_createand then attaching it with
AttachCurrentThread).
Now the stack trace looks like this:
dalvik.system.NativeStart.run(Native Method)
The topmost method is
NativeStart.run, which isn't part of your application. If you call
FindClassfrom this
thread, the JavaVM will start in the "system" class loader instead of the one associated with your application, so attempts to find app-specific classes will fail.
也就是说,当前java的VM的线程的CallStack是
dalvik.system.NativeStart.run(Native Method)
JavaVM将使用系统的class loader而不是你的应用使用的class loader. 从而去找应用自身的类,将会失败。
android也给出了几个解决方案:
There are a few ways to work around this:
Do your
FindClasslookups once, in
JNI_OnLoad, and cache the class references
for later use. Any
FindClasscalls made as part of executing
JNI_OnLoadwill use the class loader associated
with the function that called
System.loadLibrary(this is a special rule, provided to make library initialization more convenient). If your app code is loading the library,
FindClasswill
use the correct class loader.
Pass an instance of the class into the functions that need it, by declaring your native method to take a Class argument and then passing
Foo.classin.
Cache a reference to the
ClassLoaderobject somewhere handy, and issue
loadClasscalls
directly. This requires some effort.
第一种方法就是通过在本来的java线程调用c/c++的时候,来获取相应的jclass,然后缓存起来。
一般做法就是在JNI_OnLoad方法处理。 这个是有局限的。如果你的类不多,这样处理还是可行的。
第二种方法,网上的例子比较多,就是在本来的java线程中调用自定义的native函数。从而在native中缓存此对象。然后在新建的线程里面通过此对象来获取相应的class。 这个方法和上面的类似。如果类过多,就需要多个此对象。
网上有此代码。不过有些地方描述不清楚。我这边总结一下:
Java的代码
void setJNIEnv();
在应用开始的地方,调用此方法,一般是Activity的onCreate。
在c/c++端native文件中:
JavaVM *g_jvm = NULL;
jobject g_obj = NULL;
JNIEXPORT void Java_YOURCLASS_setJNIEnv( JNIEnv* env, jobject obj)
{
(*env)->GetJavaVM(env,&g_jvm);
g_obj = (*env)->NewGlobalRef(env,obj);
}
这样就建立起了全局的object。
然后在你的c/c++的线程函数中:
in your thread fund:
JNIEnv* env = NULL;
if( g_jvm->AttachCurrentThread(&env,NULL) < 0)
{
/// your error process.
}
jclass cls = (*env)->GetObjectClass(env,g_obj);
if(cls == NULL)
{
///your error process.
}
///获取到jclass, 就可以调用此class的方法了。
/// GetMethodID 和 CallVoidMethod 等各种jni方法可以调用。 class参数将cls放入。
…….
在你的线程结束的地方:调用
g_jvm->DetachCurrentThread();
既:一个native线程,开始必须调用 AttachCurrentThread. 结束调用 DetachCurrentThread。
不建议多次调用 AttachCurrentThread / DetachCurrentThread。否则可能会造成虚拟机的内存泄漏问题。
因为调用 AttachCurrentThread 是java虚拟机要创建java端的线程与之对应。 这个开销大家自己去想吧。呵呵。因此,一个线程just call one time。
从上面的过程来看,它回避了 env->FindClass的问题。
哪有没有更好的方法呢?
差不多就是android的第三种方法,通过
ClassLoaderobject来处理了。
这里写的过多了,新开第二篇来描述ClassLoader的方法。
android multithread in c/c++ to call JNI 的第二篇: /article/10219772.html
相关文章推荐
- How to use Multi-touch in Android 2 --转载
- Error (-17998): Failed to get [param not passed in call] thread TLS entry
- windows下eclipse远程连接hadoop错误“Exception in thread"main"java.io.IOException: Call to Master.Hadoop/172.20.145.22:9000 failed ”
- Android: call to OpenGL ES API with no current context (logged once per thread)
- lua教程十一----C/C++与Lua之间进行数据函数交互以及解决“PANIC: unprotected error in call to Lua API (attempt t
- How to call c++ exported method and classes in c#
- C/C++与Lua之间进行数据函数交互以及解决“PANIC: unprotected error in call to Lua API (attempt t
- [Android 問題] How to Activate Multi-Touch in WebView (for Web Browser, Google Map, etc)?
- Using AfxBeginThread for multi-thread in VS C++
- 【COCOS2DX-LUA 脚本开发之十一】C/C++与Lua之间进行数据函数交互以及解决“PANIC: unprotected error in call to Lua API (attempt t
- Android笔记-MultiThreading in Android(1)-Thread,Looper,Handler,Message,MessageQueue之间的关系
- How to start a second thread in an MFC-based ActiveX control to fire events in Visual C++
- 解决COCOS2D-X与JNI交互游戏出现崩溃的问题call to OpenGL ES API with no current context (logged once per thread)
- How To Call Run() Method of the Microsoft Script Control in C++
- 【转】How to call c++ exported method and classes in c#
- c++ g++运行出现Enable multithreading to use std::thread: Operation not permitted解决
- Android笔记-MultiThreading in Android(1)-Thread,Looper,Handler,Message,MessageQueue之间的关系
- RTandroid ADB MODE: Introduction to accessing the Raspberry Pi's GPIO in C++ (sysfs)
- An Introduction to Thread in the upcoming book From: Introduction to the C++ Boost Libraries
- How to run a Runnable thread in Android?