在上一篇中已经介绍了关于java部分中native函数的定义和具体的调用,到目前为止还没有看到如何将java接口和JNI函数的接口关联起来。具体是如何关联起来的?Java和JNI函数之间必然存在一种联系,当调用到java层的native方法的时候映射到JNI接口。这就是下面将要介绍的JNI方法的注册,其中JNI的注册方法有两种:静态注册和动态注册。
一、JNI方法的注册
1、静态注册
通过JNI函数的注册就是通过java函数名称找到对应的JNI函数,大致为如下的过程:
- 编写native类LedNative ,然后编译成.class
- 通过java SDK提供的javah命令,java -classpath path com.package.classname,生产JNI层的.h头文件。依据头文件声明的方法,编写对应的.c文件实现.h中声明的方法。
上一篇中已经编写了对象的java文件,编译之后生成了class文件。
通过javah命令 javah -classpath .\classes\ com.led.api.LedNative在bin目录中会生成一个JNI层的.h的头文件com_led_api_LedNative.h
[com_led_api_LedNative.h 头文件部分内容]
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h> //必须include该头文件,在该文件中声明了JNI层需要使用到方法和类型定义
/* Header for class com_led_api_LedNative */
#ifndef _Included_com_led_api_LedNative
#define _Included_com_led_api_LedNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_led_api_LedNative
* Method: ledPowerOn
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOn
(JNIEnv *, jclass);
/*
* Class: com_led_api_LedNative
* Method: ledPowerOff
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOff
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
对比java中声明的方法,ledPowerOn和ledPowerOff方法在JNI头文件中声明如下:
JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOn(JNIEnv *, jclass);
JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOff(JNIEnv *, jclass);
*JNI头文件声明的规则为Java_packagename_function,其中packagename中的“.”被替换为“_”,funcation中的“_”会被替换为"_l".
*JNI头文件声明的规则为Java_packagename_function,其中packagename中的“.”被替换为“_”,funcation中的“_”会被替换为"_l".
当java调用ledPowerOn方法的时候,就会从对应的JNI lib文件中找对应的Java_com_led_api_LedNative_ledPowerOn,如果找到就会建立关联,后续直接通过Java_com_led_api_LedNative_ledPowerOn函数指针进行操作,具体的对应通过java虚拟机来实现。
实现对应的C文件
[com_led_api_lednative.c]
#include<stdio.h>
#include"com_led_api_LedNative.h"
/*
* Class: com_led_api_LedNative
* Method: ledPowerOn
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOn
(JNIEnv *env, jclass clazz)
{
//TODO
printf("ledpoweron");
return 0;
}
/*
* Class: com_led_api_LedNative
* Method: ledPowerOff
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOff
(JNIEnv *env, jclass clazz)
{
//TODO
printf("ledpoweroff");
return 0;
}
最终编译JNI的.c和.h文件生成libLedJni.so文件,由于在开发板上运行,将生成的lib文件copy到/system/lib目录中,运行上一篇编译的APK。发现输出在JNI层的函数实现中输出的log信息“ledpoweroff”和"ledpoweron"。
对于其中JNI层函数的类型以及参数调用等都没有说明,但是到此为止整个JNI编写到JNI调用的过程都已经明了。