java jni 原理_一文深入理解 JNI实现机制

本文详细介绍了Java Native Interface(JNI)的工作原理,包括Java代码的编译和执行过程、JNI的使用方法、本地库(SO)的加载流程、JNIEnv的作用及其实现。文章通过示例展示了JNI的隐式和显式注册方法,并分析了JNI函数的调用过程,最后讨论了使用JNI时需要注意的事项。
摘要由CSDN通过智能技术生成

原标题:一文深入理解 JNI实现机制

写在前面

说到JNI都不陌生,它的全称:Java Native Interface,即Java本地接口。

JNI不仅仅是Android特有的,它是属于Java平台的,它允许在Java虚拟机内运行的java代码与其他编程语言(如c, c++和汇编语言)编写的程序和库进行交互。

JNI调用姿势:Java —> JNI —> C/C++(SO库)

在Android平台中,使用JNI封装了跟硬件相关的操作,从而可以通过Java调用相关JNI模块,以达到对硬件的调用。

下面我们将围绕如下内容进行展开:

1.java代码编译和执行过程

2.jni常规使用姿势

3.so加载流程(jni执行流程、注册方式原理)

4.JNIEnv作用及实现

Java代码编译和执行过程

java代码编译和执行的过程涉及到两个命令:javac和java

1.首先通过javac编译java代码,生成class字节码文件

2.javacTestCode.java --> TestCode.class

3.然后通过java命令来执行class字节码

4.javaTestCode.class

java命令执行过程中,会先启动虚拟机,加载TestCode类信息到内存,然后由执行引擎执行其main方法。

JVM的逻辑内存模型如下:

ce289cf5cd80e4dbb27e9360d2407a5f.png

9fb1771b8cef8589a22cdf4ba8c021bf.png

83e0c76dc01348e9d8f6c15adeea23a2.png

JNI常规使用姿势

在java层通过native关键字创建本地方法,如下:(成员方法、static方法)

public

classJNIMethods{

static{

System.loadLibrary( "test-jni");

}

//隐式注册

publicnativeString stringFromJNI();

publicstaticnativeString testParams(intjint, String jstring, Object jobject, Object[] arrayObject, Listlist);

//显式注册

publicnativeString stringFromJNIDis();

publicstaticnativeString testParamsDis(intjint, String jstring, Object jobject, Object[] arrayObject, Listlist);

}

创建c层代码,并注册本地方法

#include

#include

#include"common.h"

jstring stringFromJNIDis(JNIEnv *env, jobject jobj);

jstring testParamsDis(JNIEnv *env, jclass type, jint jint_, jstring jstring_, jobject jobject_, jobjectArray objectArray, jobject list);

staticjmethodID methodID_toString;

//显式注册

staticJNINativeMethod gMethods[] = {

{ "stringFromJNIDis", "()Ljava/lang/String;", ( void*) stringFromJNIDis},

{ "testParamsDis", "(ILjava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;Ljava/util/List;)Ljava/lang/String;", ( void*) testParamsDis}

};

staticintregisterNativeMethods(JNIEnv *env, constchar*className, JNINativeMethod *methods, intnMethods){

jclass clazz;

clazz = env->FindClass(className);

if(clazz == NULL) {

returnJNI_FALSE;

}

if(env->RegisterNatives(clazz, methods, nMethods) < 0) {

returnJNI_FALSE;

}

returnJNI_TRUE;

}

voidappendString(JNIEnv *env, char*dest, jstring tmpStr){

if(tmpStr == NULL) {

return;

}

constchar*tmpString = env->GetStringUTFChars(tmpStr, 0);

strcat(dest, tmpString);

env->ReleaseStringUTFChars(tmpStr, tmpString);

}

//加载so时会执行该方法

JNIEXPORT jint JNICALL JNI_(JavaVM *vm, void*reserved){

LOGD( "test-jni.cpp JNI_");

JNIEnv *env = NULL;

if(vm->GetEnv(( void**) &env, JNI_VERSION_1_4) != JNI_OK) {

return-1;

}

if( NULL== env) {

return-1;

}

jclass clazz = env->FindClass( "java/lang/Object");

methodID_toString = env->GetMethodID(clazz, "toString", "()Ljava/lang/String;");

//显式注册本地方法

if(!registerNativeMethods(env, "com/mob/test/jni/testjni/JNIMethods", gMethods, NELEM(gMethods))) {

LOGE( "test-jni.cpp JNI_ register JNIMethods failed");

}

returnJNI_VERSION_1_4;

}

//卸载时会执行该方法

JNIEXPORT voidJNI_OnUnload(JavaVM *vm, void*reserved){

LOGD( "test-jni.cpp JNI_OnUnload");

methodID_toString = NULL;

}

//隐式注册

extern"C"JNIEXPORT jstring JNICALL

Java_com_mob_test_jni_testjni_JNIMethods_stringFromJNI(JNIEnv *env, jobject jobj){

LOGD( "test-jni.cpp Java_com_mob_test_jni_testjni_JNIMethods_stringFromJNI");

returnstringFromJNIDis(env, jobj);

}

extern"C"JNIEXPORT jstring JNICALL

Java_com_mob_test_jni_testjni_JNIMethods_testParams(JNIEnv *env, jclass type, jint jint_, jstring jstring_, jobject jobject_,

jobjectArray arrayObject,

jobject list){

LOGD( "test-jni.cpp Java_com_mob_test_jni_testjni_JNIMethods_testParams");

returntestParamsDis(env, type, jint_, jstring_, jobject_, arrayObject, list);

}

//显式注册

jstring stringFromJNIDis(JNIEnv *env, jobject jobj){

LOGD( "test-jni.cpp stringFromJNIDis");

std:: stringhello = "Hello from C++";

returnenv->NewStringUTF(hello.c_str());

}

jstring testParamsDis(JNIEnv *env, jclass type, jint jint_, jstring jstring_, jobject jobject_, jobjectArray arrayObject, jobject list){

LOGD( "test-jni.cpp testParamsDis");

charreturnValue[ 1024];

inti = jint_;

sprintf(returnValue, "%d", i);

appendString(env, returnValue, jstring_);

jstring returnToString = reinterpret_cast<_jstring>(env->CallObjectMethod(jobject_, methodID_toString));

appendString(env, returnValue, returnToString);

jsize len = env->GetArrayLength(arrayObject);

jobject tmpObject;

jstring tmpString;

for(i = 0; i < len; i++) {

tmpObject = env->GetObjectArrayElement(arrayObject, i);

tmpString = reinterpret_cast<_jstring>(env->CallObjectMethod(tmpObject, methodID_toString));

appendString(env, returnValue, tmpString);

}

env->DeleteLocalRef(tmpObject);

jclass clazz_list = env->GetObjectClass( list);

jmethodID list_get = env->GetMethodID(clazz_list, "get", "(I)Ljava/lang/Object;");

jmethodID list_size = env->GetMethodID(clazz_list, "size", "()I");

intsize = env->CallIntMethod( list, list_size);

jstring itemStr;

for(i = 0; i < size; i++) {

itemStr = reinterpret_cast(env->CallObjectMethod( list, list_get, i));

appendString(env, returnValue, itemS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值