美文网首页
JNI原理分析

JNI原理分析

作者: 123yuan123 | 来源:发表于2017-12-05 10:46 被阅读0次

一基于开发Android的C++必备知识

自我感觉Android开发JNI仅仅是为了调用c库完成一些操作,所以仅仅需要了解基础的c/c++就足够了,首先jni的本地函数的必备参数就是两个结构体指针,所以最先学习结构体指针

#includestruct smile

{

char sna;

char size;

float price;

};

int main(void)

{

struct smile x;

x.sna = 'M';

x.size = 'B';

x.price = 20.5;

printf( "%c, %c, %.1f", x.sna, x.size, x.price );

return 0;}

这是一个典型的结构体定义和调用的写法,和Java的区别是不需要new对象,结构体成员变量的访问除了可以借助符号".",还可以用"->"访问,这就需要结构体的指针,后面我们会知道本地函数会将Java对象的地址传递给c,所以jni中都是指针访问的形式

#include#includestruct smile {

char sna;

float price;

};

int main(void)

{

struct smile x;

struct smile *px;

px = &x;

px->sna = 'R';

px->price = 26.8;

printf( "Sna=[%c], Price=%.1f", x.sna, x.price );

}

上面就是指针访问的形式,将定义的struct对象指针赋值给*px,就可以操作地址,因为java和c的对象不通用,所以,他们互相调用的原理虚拟机就是通过指针进行地址操作,下面就分析jni的调用过程,当我们调用system.loadlibrary()时,vm就会调用JNI_OnLoad()函数,这个函数的源码地址是/system/lib/libmedia_jni

// #define LOG_NDEBUG 0

#define LOG_TAG "MediaPlayer-JNI"

// ………

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

}

assert(env != NULL);

if (register_android_media_MediaPlayer(env) < 0) {

LOGE("ERROR: MediaPlayer native registration failed\n");

goto bail;

}

/* success -- return valid version number */

result = JNI_VERSION_1_4;

bail: return result;

}

此函数回传JNI_VERSION_1_4值给VM,于是VM知道了其所使用的JNI版本了。此外, JNI_OnLoad()函数也做了一些初期的动作,例如指令:

if (register_android_media_MediaPlayer(env) < 0) {

LOGE("ERROR: MediaPlayer native registration failed

\n");

goto bail;

}

就将此*.so的<函数名称表>登记到VM里,以便能加快后续调用本地函数之效率,Java类别透过VM而调用到本地函数。一般是仰赖VM去寻找*.so里的本地函数。如果需要连续调用很多次,每次都需要寻找一遍,会多花许多时间。此时,将此*.so的<函数名称表>登记到VM里。

接下来.so中我们实现我们的本地函数:

JNIEXPORT jstring JNICALL Java_test_yuan_codelearntest_Utils_JniUtils_test(JNIEnv *env,jobject obj)

{

returnenv -> NewStringUTF("Hello World!");

}

jobject obj表示我们的本地函数所在的类的对象,JNIEnv *env这个参数可以理解为虚拟机指针,因为虚拟机是链接Java和c的桥梁,我们可以利用这个指针操作java的性能,比如我们可以拿到对象的class:jclass clazz = (*env)->GetObjectClass(env, obj);这样就可以做一些反射的操作,比如拿到函数id:  m_mid = (*env)->GetMethodID(env, clazz, "setV", "(I)V");从C调用java函数:(*env)->CallVoidMethod(env, thiz, m_mid, sum);等等操作

相关文章

  • JNI原理分析

    一基于开发Android的C++必备知识 自我感觉Android开发JNI仅仅是为了调用c库完成一些操作,所以仅仅...

  • 2016.6

    6.1 Retrofit2源码分析(一) Android JNI原理分析 扫清Android面试障碍 高仿网易新闻...

  • JNI原理

    JNI实现原理 JNI系列:JavaVM和JNIEnv等原理http://blog4jimmy.com/2017/...

  • JNI-从jvm源码分析Thread.interrupt的系统级

    JNI-从jvm源码分析Thread.interrupt的系统级别线程打断原理[https://www.cnblo...

  • NDK开发基础①使用Android Studio编写NDK

    接续上个系列之 [ JNI开发系列 ]:JNI开发系列①JNI概念及开发流程JNI开发系列②.h头文件分析JNI开...

  • JNI原理

    目录 JNI概述 MediaRecorder框架中的JNI Java Framework层的MediaRecord...

  • JNI 原理

    我们都知道JNI结构是 Java 层 -> JNI -> Native 层, 以此实现Java 层和Native层...

  • 深入理解JNI

    #1 JNI概述 #2 学习JNI实例:MediaScanner #3 Java层的MediaScanner分析 ...

  • Android JNI概述

    本文基于Android 9.0源码分析 Android JNI简介 JNI是Java Native Interfa...

  • ijkplayer 分析 -- 流程

    ijkplayer源码地址:ijkplayer (以播放rtmp源分析,jni函数在(Ijkplayer_jni....

网友评论

      本文标题:JNI原理分析

      本文链接:https://www.haomeiwen.com/subject/atrwbxtx.html