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"); }