1. 程式人生 > >java jni 標頭檔案生成

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