执行System.loadLibrary()函数时,VM会反向调用*.so里的JNI_OnLoad()函数。用途有二:
1. VM询问此*.so使用的JNI版本编号。
2. VM要求*.so做一些初期设定工作(Initialization),例如登记<函数名称表>。
•例如,在Android的jniload.so档案里,就提供了JNI_OnLoad()函数,其程序码片段为:
/* com.misoo.counter.CounterNative.cpp */ #include <stdio.h> #include<jni.h> #include <pthread.h> #include<android/log.h> #include "com_misoo_counter_CounterNative.h" //LOGE("ERROR: GetEnv failed "); #define LOGE(x) __android_log_print(ANDROID_LOG_INFO,TAG,(x)) jmethodID mid; jclass mClass; JavaVM *jvm; pthread_t thread; int n, sum; const char *TAG="JniTest"; //int ANDROID_LOG_INFO= 0; void* trRun(void*); void JNICALL Java_com_misoo_counter_CounterNative_nativeSetup(JNIEnv *env, jobject thiz) { jclass clazz = env->GetObjectClass(thiz); mClass = (jclass) env->NewGlobalRef(clazz); mid = env->GetStaticMethodID(mClass, "callback", "(I)V"); } void JNICALL Java_com_misoo_counter_CounterNative_nativeExec(JNIEnv *env, jobject thiz, jint numb) { n = numb; pthread_create(&thread, NULL, trRun, NULL); } void* trRun(void*) { int status; JNIEnv *env; bool isAttached = false; status = jvm->GetEnv((void **) &env, JNI_VERSION_1_4); if (status < 0) { status = jvm->AttachCurrentThread(&env, NULL); if (status < 0) return NULL; isAttached = true; } sum = 0; for (int i = 0; i <= n; i++) sum += i; env->CallStaticVoidMethod(mClass, mid, sum); if (isAttached) jvm->DetachCurrentThread(); return NULL; } static const char *classPathName = "com/misoo/counter/CounterNative"; static JNINativeMethod methods[] = { { "init", "()V", (void *) Java_com_misoo_counter_CounterNative_nativeSetup }, { "execute", "(I)V", (void *) Java_com_misoo_counter_CounterNative_nativeExec } }; static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) { __android_log_print(ANDROID_LOG_INFO,TAG,"registerNativeMethods"); if(env == NULL) __android_log_print(ANDROID_LOG_INFO,TAG,"env is null"); jclass clazz = env->FindClass(className); __android_log_print(ANDROID_LOG_INFO,TAG,"find class"); __android_log_print(ANDROID_LOG_INFO,TAG,"%s",className); env->RegisterNatives(clazz, gMethods, numMethods); __android_log_print(ANDROID_LOG_INFO,TAG,"end registerNativeMethods"); return JNI_TRUE; } static int registerNatives(JNIEnv* env) { __android_log_print(ANDROID_LOG_INFO,TAG,"registerNatives"); registerNativeMethods(env, classPathName, methods, sizeof(methods) / sizeof(methods[0])); __android_log_print(ANDROID_LOG_INFO,TAG,"end registerNatives"); return JNI_TRUE; } jint JNI_OnLoad(JavaVM* vm, void* reserved) { __android_log_print(ANDROID_LOG_INFO,TAG,"JNI_OnLoad"); JNIEnv *env = NULL; jvm = vm; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE("ERROR: GetEnv failed "); // return -1; } // assert(env == NULL); if (registerNatives(env) != JNI_TRUE) return -1; __android_log_print(ANDROID_LOG_INFO,TAG,"JNI_OnLoad end"); return JNI_VERSION_1_4; }
Android.mk文件是:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog LOCAL_MODULE :=jniload LOCAL_SRC_FILES :=archMultiThread.cpp include $(BUILD_SHARED_LIBRARY)
Application.mk文件:
APP_STL:=gnustl_static APP_CPPFLAGS:=-frtti -fexceptions APP_ABI:=armeabi armeabi-v7a APP_PLATFORM=android-8
CounterNative.java
package com.misoo.counter; import com.example.hellondk.MainActivity; import android.os.Handler; import android.os.Message; import android.util.Log; //CounterNative.java // ……… public class CounterNative { private static Handler h; public static final String TAG = "JniTest"; static { Log.i(CounterNative.TAG, "try to load libMyJT002.so"); System.loadLibrary("jniload"); Log.i(CounterNative.TAG, "end try to load libMyJT002.so"); } public CounterNative() { Log.i(CounterNative.TAG, "new CounterNative"); init(); Log.i(CounterNative.TAG, "init finished"); h = new Handler() { public void handleMessage(Message msg) { MainActivity.ref.setTitle("Hello …"); } }; } private static void callback(int a) { Message m = h.obtainMessage(1, a, 3, null); h.sendMessage(m); } private native void init(); public native void execute(int numb); }
package com.example.hellondk; import java.sql.Ref; import com.huml.ndk1.NativeJniAdder; import com.misoo.counter.CounterNative; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MainActivity extends Activity { public static MainActivity ref = null; CounterNative obj; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ref= this; Log.i(CounterNative.TAG, "onCreate"); obj = new CounterNative(); } //对应一个Button的onClick事件,布局文件中一个Button按钮,布局文件很简单我就不列出来了 public void TestNDK(View view){ Log.i(NativeJniAdder.TAG, "start NDK"); obj.execute(11); } }