1. JNI 入门
最近学习了下JNI,记录下感受。
JNI(Java NativeInterface), its objective is to call those function which has implemented inlower-level programming language, such as C, C++
Implement steps:
S1. Write the JAVA classwith Native declaration
public classCamcorderProfile{
……
static {
System.loadLibrary("media_jni");
native_init();
}
private staticnative final voidnative_init();
private static native finalCamcorderProfile native_get_camcorder_profile(int cameraId, int quality);
private static native final booleannative_has_camcorder_profile(
int cameraId, int quality);}
声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。
Load动态库:System.loadLibrary("media_jni");加载动态库(我们可以这样理解:我们的方法 native_init()没有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载 的。同时需要注意的是System.loadLibrary();的参数“media_jni”是动态库的名字。
S2. 编写本地方法
static void
android_media_MediaScanner_native_init(JNIEnv*env)
static JNINativeMethodgMethodsForCamcorderProfileClass[] = {
{"native_init","()V", (void *)android_media_MediaScanner_native_init },
}
2. JNI 流程
Windows系统上的java体系
java程序中则是jvm通过加载并调用此jni程序来间接地调用目标原生函数。
Jni调用过程示意图
3. Android JNINativeMethod
a .JNINativeMethod
Andoird 中使用了一种不同传统Java JNI的方式来定义其native的函数。其中很重要的区别是Andorid使用了一种Java 和 C 函数的映射表数组,并在其中描述了函数的参数和返回值。这个数组的类型是JNINativeMethod,定义如下:
typedef struct{
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
第一个变量name是Java中函数的名字。
第二个变量signature,用字符串是描述了函数的参数和返回值
第三个变量fnPtr是函数指针,指向C函数。
其中比较难以理解的是第二个参数,例如
"()V" void Func()
"(II)V" void Func(int, int)
"(Ljava/lang/String;Ljava/lang/String;)V"
具体的每一个字符的对应关系如下
字符 Java类型 C类型 长度
V void void n/a
Z jboolean boolean 8
I jint int 32
J jlong long 64
D jdouble double 64
F jfloat float 32
B jbyte byte 8
C jchar char 16
S jshort short 16
数组则以”[“开始,用两个字符表示
[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]
上面的都是基本类型。如果Java函数的参数是class,则以”L”开头,以”;”结尾中间是用”/” 隔开的包及类名。而其对应的C函数名的参数则为jobject. 一个例外是String类,其对应的类为jstring
Ljava/lang/String; String jstring
static JNINativeMethodgMethodsForCameraProfileClass[] = {
{"native_init","()V",(void *)android_media_MediaProfiles_native_init},
{"native_get_num_image_encoding_quality_levels","(I)I", (void*)android_media_MediaProfiles_native_get_num_image_encoding_quality_levels},
{"native_get_image_encoding_quality_level","(II)I", (void*)android_media_MediaProfiles_native_get_image_encoding_quality_level},
};
b.注册JNI
static const char* const kCamcorderProfileClassPathName ="android/media/CamcorderProfile";
int register_android_media_MediaProfiles(JNIEnv *env)
{ int ret2 = AndroidRuntime::registerNativeMethods(env,
kCamcorderProfileClassPathName,
gMethodsForCamcorderProfileClass,
NELEM(gMethodsForCamcorderProfileClass)),
Return ret2;}
c.JNI_OnLoad
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;
LOGI("JNI_OnLoad");
if (register_android_media_MediaProfiles(env) < 0) {
LOGE("ERROR: MediaProfiles native registration failed");
goto fail;}
/* success -- return valid version number */
result = JNI_VERSION_1_4;
fail:
return result;}