您的位置:首页 > 移动开发 > Android开发

Android JNI开发解析

2019-05-07 12:26 92 查看

1.JNI简介

JNI的含义:Java native interface,是为了方便Java调用C、C++本地代码所封装的一层接口

2.JavaVM和JNIEnv

JNI定义了两个关键数据结构,“JavaVM”和“JNIEnv”。这两者基本上都是指向函数表指针的指针。(在C ++版本中,它们是带有指向函数表的指针的类,以及用于指向表中的每个JNI函数的成员函数。)

JavaVM提供“调用接口”函数,允许您创建和销毁JavaVM的。理论上,每个进程可以有多个JavaVM,但Android只允许一个。

JNIEnv提供了大多数JNI功能。本地函数都接收JNIEnv作为第一个参数。

3.jclass,jmethodID和jfieldID

如果要从本机代码访问对象的字段,请执行以下操作:

  • 获取类的类对象引用 FindClass
  • 获取该字段的字段ID GetFieldID
  • 使用适当的内容获取字段的内容,例如 GetIntField

4.JNI的注册方式

JVM 查找 4000 native 方法有两种方式:

  • 按照 JNI 规范的命名规则(静态注册)
  • 调用 JNI 提供的 RegisterNatives 函数,将本地函数注册到 JVM 中(动态注册)

4.1静态注册实现:

com_ad_jnidemo_JniUtils.h代码如下:
#ifndef _Included_com_ad_jnidemo_JniUtils
#define _Included_com_ad_jnidemo_JniUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     com_ad_jnidemo_JniUtils
* Method:    getJniString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ad_jnidemo_JniUtils_getJniString
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

注意:以上的com_ad_jnidemo_JniUtils.h文件是根据执行命令javah com.ad.jnidemo.JniUtils .java所生成的文件。

com_ad_jnidemo_JniUtils.cpp代码如下:
#include "com_ad_jnidemo_JniUtils.h"

JNIEXPORT jstring JNICALL Java_com_ad_jnidemo_JniUtils_getJniString
(JNIEnv *env, jclass) {
// new 一个字符串,返回Hello World
return env -> NewStringUTF("Hello World From Jni");
}
Java调用实现, JniUtils.java代码如下:
public class JniUtils {

static {
System.loadLibrary("JNIUtils");
}

//native接口,将调用com_ad_jnidemo_JniUtils.cpp中的Java_com_ad_jnidemo_JniUtils_getJniString()方法
//静态注册
public static native String getJniString();
}

4.2动态注册实现:

com_ad_jnidemo_JniUtils.h代码不变,跟上面静态注册代码一样;
com_ad_jnidemo_JniUtils.cpp代码如下:
#include <assert.h>
#include "com_ad_jnidemo_JniUtils.h"

///////////////////////////////////////////////////////////////////////
/*
* Static register
*/
JNIEXPORT jstring JNICALL Java_com_ad_jnidemo_JniUtils_getJniString
(JNIEnv *env, jclass) {
// new 一个字符串,返回Hello World
return env -> NewStringUTF("Hello World From Static Reg Jni");
}

///////////////////////////////////////////////////////////////////////
/*
* Dynamic register
*/

//步骤一:定义需要注册的java文件
#define JNIREG_CLASS "com/ad/jnidemo/JniUtils"

//步骤二:编写C++层的实现函数
jstring dynamic_reg_getJniString(JNIEnv* env, jobject thiz){
return env -> NewStringUTF("Hello World From Dynamic Reg Jni");
}

//步骤三:方法对应表
//"getJniStringFromDynamicReg",注册java文件"com/ad/jnidemo/JniUtils"中的接口
//dynamic_reg_getJniString,C++层的实现函数
static JNINativeMethod gMethods[] = {
{"getJniStringFromDynamicReg", "()Ljava/lang/String;", (void *) dynamic_reg_getJniString},
};

//步骤四:为某一个类注册本地方法,主要注册"com/ad/jnidemo/JniUtils"文件
static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) {
jclass clazz;
clazz = (env)->FindClass( className);
if (clazz == NULL) {
return JNI_FALSE;
}
if ((env)->RegisterNatives(clazz, gMethods, numMethods) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}

//同步骤四,为所有类注册本地方法
static int registerNatives(JNIEnv* env) {
return registerNativeMethods(env, JNIREG_CLASS, gMethods,sizeof(gMethods) / sizeof(gMethods[0]));
}

//步骤五:执行动态注册
/*
* System.loadLibrary("lib")时调用
* 如果成功返回JNI版本, 失败返回-1
*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;
if (( vm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK)) {
return -1;
}
assert(env != NULL);
if (!registerNatives(env)) {//注册
return -1;
}

result = JNI_VERSION_1_6;
return result;
}

实现关键步骤,请参照代码注释中的步骤一、二、三、四、五。

Java调用实现, JniUtils.java代码如下:
package com.ad.jnidemo;

public class JniUtils {

static {
System.loadLibrary("JNIUtils");
}

//native接口,将调用com_ad_jnidemo_JniUtils.cpp中的Java_com_ad_jnidemo_JniUtils_getJniString()方法
//静态注册
public static native String getJniString();

//动态注册接口
public static native String getJniStringFromDynamicReg();
}

4.3 mk编译文件

Android.mk文件如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := JNIUtils
LOCAL_SRC_FILES := com_ad_jnidemo_JniUtils.cpp

include $(BUILD_SHARED_LIBRARY)

Application.mk文件如下:

APP_MODULES := JNIUtils
APP_ABI := all
APP_STL = c++_static
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: