java jni 標頭檔案生成
jni標頭檔案生成
eclipse下
eclpse下,在java類程式碼中載入jni動態庫,定義好native函式後,在專案程式碼目錄的bin\classes下,cmd輸入命令:javah -jni 類名如 >javah -jni com.skyworth.autotest.common.Aut
oTestParamTrans後就會在bin\classes生成標頭檔案,然後實現該標頭檔案中的函式即可;
package com.penghui.testjni;
public class Autotest{
public native boolean isConnected ();
static
{
System.loadLibrary("hello");
}
}
執行:javah -jni com.penghui.testjni.Autotest
其他方式
命令列下,如linux下或者直接用Windows的cmd
假如手動編輯上述java程式碼:
1. 先新建com/penghui/testjni/目錄
2. cd到新建的目錄中編輯上述程式碼Autotest.java
3. 然後cd到原目錄,執行javac com/penghui/testjni/Autotest.java在com/penghui/testjni/下生成Autotest.class
4. 執行javah -jni com.penghui.testjni.Autotest 在 本目錄生成com_penghui_testjni_Autotest.h(注意,如果之前存在com_penghui_testjni_Autotest.h,需要先刪掉,在執行命令生成)
com_penghui_testjni_Autotest.h內容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_penghui_testjni_Autotest */
#ifndef _Included_com_penghui_testjni_Autotest
#define _Included_com_penghui_testjni_Autotest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_penghui_testjni_Autotest
* Method: isConnected
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_penghui_testjni_Autotest_isConnected
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
JNI_OnLoad與JNI_OnUnload
在Android中,當程式在java層執行System.loadLibrary(“jnitest”);這行程式碼後,程式會去載入libjnitest.so檔案,與此同時,產生一個”Load”事件,這個事件觸發後,程式預設會在載入的.so檔案的函式列表中查詢JNI_OnLoad函式並執行,與”Load”事件相對,當載入的.so檔案被解除安裝時,“Unload”事件被觸發,此時,程式預設會去在載入的.so檔案的函式列表中查詢JNI_OnUnload函式並執行,然後解除安裝.so檔案。需要注意的是,JNI_OnLoad與JNI_OnUnload這兩個函式在.so元件中並不是強制要求的,使用者也可以不去實現,java程式碼一樣可以呼叫到C元件中的函式,在接下來的章節中會講到這點。
之所以在C元件中去實現這兩個函式(特別是JNI_OnLoad函式),往往是做一個初始化工作或“善後”工作。可以這樣認為,將JNI_ONLoad看成是.so元件的初始化函式,當其第一次被裝載時被執行(window下的dll檔案也可類似的機制,在_DLL_Main()函式中,通過一個swith case語句來識別當前是載入還是解除安裝)。將JNI_OnUnload函式看成是解構函式,當其被解除安裝時被呼叫。
由此看來,就不難明白為什麼很多jni C元件中會實現JNI_OnLoad這個函數了。 一般情況下,在C元件中的JNI_OnLoad函式用來實現給VM註冊介面,以方便VM可以快速的找到Java程式碼需要呼叫的C函式。(此外,JNI_OnLoad函式還有另外一個功能,那就是告訴VM此C元件使用那一個JNI版本,如果未實現JNI_OnLoad函式,則預設是JNI 1.1版本)。
使用顯式註冊native jni方法
static JNINativeMethod gMethods[] = {
{"isConnected","()I",(void *)isconnect}
};
static int register_com_penghui_testjni(JNIEnv *env)
{
return AndroidRuntime::registerNativeMethods(env,
"com/penghui/testjni/Autotest", gMethods, NELEM(gMethods));
}
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
//LOGE("ERROR: GetEnv failed\n");
goto FAIL;
}
assert(env != NULL);
if (register_com_penghui_testjni(env) < 0) {
goto FAIL;
}
// media_jniTest
/* success -- return valid version number */
result = JNI_VERSION_1_4;
//LOGV("Leave %s %d", __FUNCTION__, __LINE__);
FAIL:
return result;
}