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