標籤:
執行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\n");#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\n");// 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 -llogLOCAL_MODULE :=jniloadLOCAL_SRC_FILES :=archMultiThread.cppinclude $(BUILD_SHARED_LIBRARY)
Application.mk檔案:
APP_STL:=gnustl_static APP_CPPFLAGS:=-frtti -fexceptions APP_ABI:=armeabi armeabi-v7aAPP_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); } }
android JNI學習之一