第14節(jniのマルチスレッド)
6203 ワード
ログに関する知識点を見てjniでログを出力するとき:
そして、jniでLOGIを使ってログを出力することができます.
質問:
各スレッドのJNIEnvインスタンスは互いに独立しているので、jniで新しいスレッドを開くには、そのスレッドのJNIEnvインスタンスを作成する必要があります.
MainActivity.java
残りの2つの方法はjniの新しいスレッドからコールバックするnative-libである.cpp
ログをlogcatで見てみましょう.
//MainActivityオブジェクトjob=env->NewGlobalRef(clazz)を保存します.メモリが漏れる可能性があります.メモリを解放する方法は、次のとおりです.
#define TAG "JNI"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
そして、jniでLOGIを使ってログを出力することができます.
質問:
jni , MainActivity
各スレッドのJNIEnvインスタンスは互いに独立しているので、jniで新しいスレッドを開くには、そのスレッドのJNIEnvインスタンスを作成する必要があります.
1. JavaVM
2. JNIEnv
MainActivity.java
private native void setJNIEnv();
private native void newThreadInJNI();
private static void callStaticBack(int value)
{
Log.e("abc","from static----->"+value);
}
private void callBack(int value)
{
Log.e("abc","from ----->"+value);
}
1. onCreate setJNIEnv()
2. newThreadInJNI()
残りの2つの方法はjniの新しいスレッドからコールバックするnative-libである.cpp
#include
#include
#include
#include
#include
#include
#define TAG "HZP_JNI"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
//
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
JavaVM *javaVM=NULL;
jobject job=NULL;// MainActivity
JNIEXPORT void JNICALL native_setJNIEnv
(JNIEnv *env, jclass clazz) {
env->GetJavaVM(&javaVM);
// MainActivity
job=env->NewGlobalRef(clazz);
}
void *start_thread(void * args)
{
JNIEnv * env;
if((javaVM->AttachCurrentThread(&env,NULL))!=JNI_OK)
{
LOGI("%s AttachCurrentThread error failed ",__FUNCTION__);
return NULL;
}
jclass jcl;
jmethodID jsmd;
jmethodID jmd;
jcl=env->GetObjectClass(job);
if(jcl==NULL)
{
LOGI("findClass error....");
goto error;
}
LOGI("call static back begin");
jsmd=env->GetStaticMethodID(jcl,"callStaticBack","(I)V");
if(jsmd==NULL)
{
LOGI("GetStaticMethodID error....");
goto error;
}
env->CallStaticVoidMethod(jcl,jsmd,(int)((size_t)args));
LOGI("call back begin");
jmd=env->GetMethodID(jcl,"callBack","(I)V");
if(jmd==NULL)
{
LOGI("GetMethodID error....");
goto error;
}
env->CallVoidMethod(job,jmd,(int)((size_t)args));
error:
if((javaVM->DetachCurrentThread())!=JNI_OK)
{
LOGI("%s DetachCurrentThread error failed ",__FUNCTION__);
}
pthread_exit(0);
}
JNIEXPORT void JNICALL native_newThreadInJNI
(JNIEnv *env, jclass clazz) {
pthread_t pt[5];
for(int i=0;i<5;i++)
{
pthread_create(&pt[i],NULL,&start_thread,(void*)i);
}
}
const JNINativeMethod gMethods[] = {
{
"setJNIEnv","()V",(void*)native_setJNIEnv
},
{
"newThreadInJNI","()V",(void*)native_newThreadInJNI
}
};
int registerNatives(JNIEnv* engv)
{
LOGI("registerNatives begin");
jclass clazz;
clazz = engv -> FindClass("com/example/huozhenpeng/myapplication/MainActivity");
if (clazz == NULL) {
LOGI("clazz is null");
return JNI_FALSE;
}
if (engv ->RegisterNatives( clazz, gMethods, NELEM(gMethods)) < 0) {
LOGI("RegisterNatives error");
return JNI_FALSE;
}
return JNI_TRUE;
}
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
LOGI("jni_OnLoad begin");
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGI("ERROR: GetEnv failed
");
return -1;
}
assert(env != NULL);
registerNatives(env);
return JNI_VERSION_1_4;
}
ログをlogcatで見てみましょう.
hhh:~ huozhenpeng$ adb logcat -v threadtime -> ./log.txt
10-04 19:22:00.330 23213 23876 I HZP_JNI : call static back begin
10-04 19:22:00.330 23213 23879 I HZP_JNI : call static back begin
10-04 19:22:00.330 23213 23879 E abc : from static----->4
10-04 19:22:00.330 23213 23876 E abc : from static----->1
10-04 19:22:00.330 23213 23879 I HZP_JNI : call back begin
10-04 19:22:00.330 23213 23876 I HZP_JNI : call back begin
10-04 19:22:00.331 23213 23879 E abc : from ----->4
10-04 19:22:00.331 23213 23876 E abc : from ----->1
10-04 19:22:00.332 23213 23878 I HZP_JNI : call static back begin
10-04 19:22:00.332 23213 23878 E abc : from static----->3
10-04 19:22:00.332 23213 23878 I HZP_JNI : call back begin
10-04 19:22:00.332 23213 23877 I HZP_JNI : call static back begin
10-04 19:22:00.332 23213 23878 E abc : from ----->3
10-04 19:22:00.332 23213 23877 E abc : from static----->2
10-04 19:22:00.332 23213 23877 I HZP_JNI : call back begin
10-04 19:22:00.333 23213 23877 E abc : from ----->2
10-04 19:22:00.334 23213 23875 I HZP_JNI : call static back begin
10-04 19:22:00.335 23213 23875 E abc : from static----->0
10-04 19:22:00.335 23213 23875 I HZP_JNI : call back begin
10-04 19:22:00.335 23213 23875 E abc : from ----->0
//MainActivityオブジェクトjob=env->NewGlobalRef(clazz)を保存します.メモリが漏れる可能性があります.メモリを解放する方法は、次のとおりです.
private native void releaseGloableRefJNI();
@Override
protected void onDestroy() {
super.onDestroy();
releaseGloableRefJNI();
}
const JNINativeMethod gMethods[] = {
{
"setJNIEnv","()V",(void*)native_setJNIEnv
},
{
"newThreadInJNI","()V",(void*)native_newThreadInJNI
}
,
{
"releaseGloableRefJNI","()V",(void*)native_releaseGloableRefJNI
}
};
JNIEXPORT void JNICALL native_releaseGloableRefJNI
(JNIEnv *env, jclass clazz) {
env->DeleteGlobalRef(job);
}