Android NDK 多线程初步学习

package com.ndk.cjava.exchange;

import java.io.Serializable;

import android.util.Log;

public class UserEntity implements Serializable {

	private static final long serialVersionUID = -8623782232814941002L;
	
	private static final String TAG_NAME = "UserEntity";
	
	private String name; 
	
	private String id;
	
	public native UserEntity copyUserEntity();
	
	public native static UserEntity newUserEntity(String id,String name);
	
	public native void update(String id,String name);
	
	public void setName(String name)
	{
		this.name = name;
	}
	
	public String getName()
	{
		return name;
	}
	public static String tag()
	{
		return UserEntity.class.getName();
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
	
	@Override
	public String toString() {
		return "UserEntity [name=" + name + ", id=" + id + "]";
	}
	
	private void throwNewException()
	{
		throw new NullPointerException("Null Pointer");
	}
	
	//对象的引用
	public native void referenceUnit();
	
    //本地方法
     public native void mainThread();

     public native void setJNIEnv(); 
     
   //由JNI中的线程回调
     private static void fromJNI(int i)
     {
         Log.v("Java------>", ""+i);
     }
	
	static{
		System.loadLibrary("NDK_Exchange");
	}
}

-----实现类-------

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include <android/log.h>

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "native-activity", __VA_ARGS__))

//全局引用对象
jclass globalJclazz = NULL;
jclass weakclass = NULL;


//线程数
#define NUMTHREADS 5
 //全局变量
JavaVM *g_jvm = NULL;
jobject g_obj = NULL;

/*
 * Class:     com_ndk_cjava_exchange_UserEntity
 * Method:    copyUserEntity
 * Signature: ()Lcom/ndk/cjava/exchange/UserEntity;
 */
JNIEXPORT jobject JNICALL Java_com_ndk_cjava_exchange_UserEntity_copyUserEntity
  (JNIEnv *env, jobject thiz)
{
	jclass jclazz = env->GetObjectClass(thiz);
	jmethodID jConstructor= env->GetMethodID(jclazz,"<init>","()V");
	jobject newInstance = env->NewObject(jclazz,jConstructor);

	jfieldID nameField =  env->GetFieldID(jclazz,"name","Ljava/lang/String;");
	jfieldID idField = env->GetFieldID(jclazz,"id","Ljava/lang/String;");

	env->SetObjectField(newInstance,nameField,env->GetObjectField(thiz,nameField));
	env->SetObjectField(newInstance,idField,env->GetObjectField(thiz,idField));

	return newInstance;
}
/*
 * Class:     com_ndk_cjava_exchange_UserEntity
 * Method:    newUserEntity
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Lcom/ndk/cjava/exchange/UserEntity;
 */
JNIEXPORT jobject JNICALL Java_com_ndk_cjava_exchange_UserEntity_newUserEntity
  (JNIEnv * env, jclass clazz, jstring id, jstring name)
{
		jmethodID jConstructor= env->GetMethodID(clazz,"<init>","()V");
		jobject newInstance = env->NewObject(clazz,jConstructor);

		jfieldID nameField =  env->GetFieldID(clazz,"name","Ljava/lang/String;");
		jfieldID idField = env->GetFieldID(clazz,"id","Ljava/lang/String;");

		env->SetObjectField(newInstance,nameField,name);
		env->SetObjectField(newInstance,idField,id);

		return newInstance;
}

/*
 * Class:     com_ndk_cjava_exchange_UserEntity
 * Method:    update
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_ndk_cjava_exchange_UserEntity_update
  (JNIEnv * env, jobject thiz, jstring id, jstring name)
{
	jclass jclz = env->GetObjectClass(thiz);
	jmethodID  setNameMethod 	=  env->GetMethodID(jclz,"setName","(Ljava/lang/String;)V");
	jmethodID  setIdMethod 		=  env->GetMethodID(jclz,"setId","(Ljava/lang/String;)V");

	env->CallVoidMethod(thiz,setNameMethod,name);
	env->CallVoidMethod(thiz,setIdMethod,id);

	jmethodID getNameMethod =   env->GetMethodID(jclz,"getName","()Ljava/lang/String;");
	jmethodID getIdMethod 	=   env->GetMethodID(jclz,"getId","()Ljava/lang/String;");

	jstring mName = (jstring)(env->CallObjectMethod(thiz,getNameMethod));
	jstring mId = (jstring)(env->CallObjectMethod(thiz,getIdMethod));

	jmethodID sTagMethod = env->GetStaticMethodID(jclz,"tag","()Ljava/lang/String;");
	jstring jtag = (jstring)(env->CallStaticObjectMethod(jclz,sTagMethod));
	jboolean isCopy;

	const char * chName = env->GetStringUTFChars(mName,&isCopy);
	const char * chId = env->GetStringUTFChars(mId,&isCopy);
	const char * chTag = env->GetStringUTFChars(jtag,&isCopy);

	jfieldID TagNamefiledId = env->GetStaticFieldID(jclz,"TAG_NAME","Ljava/lang/String;");
	jstring jtagName = (jstring)(env->GetStaticObjectField(jclz,TagNamefiledId));
	const char * chTagName =  env->GetStringUTFChars(jtagName,&isCopy);

	__android_log_print(ANDROID_LOG_ERROR,chTag,"TAG_NAME=%s,name=%s,id=%s",chTagName,chName,chId);



	//异常处理---java代码抛出的异常导致jvm shut down
	/**
	jmethodID  throwNewExceptionMethodID = env->GetMethodID(jclz,"throwNewException","()V");
	env->CallCharMethod(thiz,throwNewExceptionMethodID);
	jthrowable tr = env->ExceptionOccurred();
	if(tr!=NULL)
	{
		env->ExceptionClear();
	}
	**/

	//主动抛出异常---c抛出的异常程序不会停止
	env->ThrowNew(jclz,"主动抛出的异常");
	jthrowable tr = env->ExceptionOccurred();
	if(tr!=NULL)
	{
		env->ExceptionClear();
		env->DeleteLocalRef(jclz);
	}

}

/*
 * Class:     com_ndk_cjava_exchange_UserEntity
 * Method:    referenceUnit
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_ndk_cjava_exchange_UserEntity_referenceUnit
  (JNIEnv * env, jobject thiz)
{
	/*if(globalJclazz==NULL)
	{
		__android_log_print(ANDROID_LOG_INFO,"REF","--1-->");
		globalJclazz = (jclass)(env->NewGlobalRef(env->GetObjectClass(thiz)));
	}else{
		__android_log_print(ANDROID_LOG_INFO,"REF","--2-->");
		 env->DeleteGlobalRef(globalJclazz);
	 	 globalJclazz = NULL;
	}*/

	//
	if(weakclass==NULL || (env->IsSameObject(weakclass,NULL))==JNI_TRUE)
	{
		jclass jclzz  = env->GetObjectClass(thiz);
		weakclass = (jclass)(env->NewWeakGlobalRef(jclzz));
	}else{
		env->DeleteWeakGlobalRef(weakclass);
		weakclass = NULL;
	}
}


/****---------------------------------------多线程---------------------------------------***/
void *thread_fun(void* arg)
{
    JNIEnv * env = NULL;
    jclass cls = NULL;
    jmethodID mid = NULL;
    //Attach主线程
    if(g_jvm->AttachCurrentThread( &env, NULL) != JNI_OK)
    {
        LOGE("%s: AttachCurrentThread() failed", __FUNCTION__);
        return NULL;
    }
    //找到对应的类
    cls = env->GetObjectClass(g_obj);
    if(cls == NULL)
    {
        LOGE("FindClass() Error.....");
        goto error;
    }
    //再获得类中的方法
    mid = env->GetStaticMethodID( cls, "fromJNI", "(I)V");
    if (mid == NULL)
    {
        LOGE("GetMethodID() Error.....");
        goto error;
    }
    //最后调用java中的静态方法
    env->CallStaticVoidMethod( cls, mid ,(int)arg);
error:
    //Detach主线程
    if(g_jvm->DetachCurrentThread() != JNI_OK)
    {
        LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
    }
    pthread_exit(0);
}

JNIEXPORT void JNICALL Java_com_ndk_cjava_exchange_UserEntity_mainThread
  (JNIEnv * env, jobject thiz)
{
	 int i;
	 pthread_t pt[NUMTHREADS];
	 for (i = 0; i < NUMTHREADS; i++)
	 {   //创建子线程
	     pthread_create(&pt[i], NULL, &thread_fun, (void *)i);
	 }
}

JNIEXPORT void JNICALL Java_com_ndk_cjava_exchange_UserEntity_setJNIEnv
  (JNIEnv * env, jobject thiz)
{
	 //保存全局JVM以便在子线程中使用
     env->GetJavaVM(&g_jvm);
     //不能直接赋值(g_obj = obj)
     g_obj = env->NewGlobalRef(thiz);//变为全局变量
}

//当动态库被加载时这个函数被系统调用
 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
 {
	 LOGE("JNI_OnLoad");
     JNIEnv* env = NULL;
     jint result = -1;
     //获取JNI版本
     if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
     {
         LOGE("GetEnv failed!");
         return result;
     }
     return JNI_VERSION_1_4;
 }
 //当动态库被卸载时这个函数被系统调用
 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved)
 {
	 LOGE("JNI_OnUnload");
 }



你可能感兴趣的:(Android NDK 多线程初步学习)