`
weihe6666
  • 浏览: 430233 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

jni方法的注册和调用流程

 
阅读更多

JNI在android中起重要作用,是连接java层和dalvik重要的通道,java层的开发也比较简单,有两种注册方式:
1. 按照JNI格式声明native函数并在c文件中定义此native函数
2. 动态注册,在c文件中重写JNI_OnLoad函数,并在JNI_OnLoad中调用JNIEnv函数RegisterNatives注册native方法。


看似简单的注册和调用,背后隐藏着复杂的理论,下面就来分析一下RegisterNatives方法的逻辑。


RegisterNatives源码如下:jni.cpp
static jint RegisterNatives(JNIEnv* env, jclass jclazz,
    const JNINativeMethod* methods, jint nMethods)
{
  .......
    for (int i = 0; i < nMethods; i++) {
        if (!dvmRegisterJNIMethod(clazz, methods[i].name,
                methods[i].signature, methods[i].fnPtr))
        {
            return JNI_ERR;
        }
    }
    return JNI_OK;
}


这里主要逻辑调用dvmRegisterJNIMethod方法。

继续跟踪,此方法比较复杂,我们只分析关键语句。
    method->fastJni = fastJni;
    dvmUseJNIBridge(method, fnPtr);

    ALOGV("JNI-registered %s.%s:%s", clazz->descriptor, methodName, signature);
    return true;


这里调用了dvmUseJNIBridge函数,这是注册的核心函数,其关键语句需要详细分析:
void dvmUseJNIBridge(Method* method, void* func) {
    method->shouldTrace = shouldTrace(method);

    // Does the method take any reference arguments?
    method->noRef = true;
    const char* cp = method->shorty;
    while (*++cp != '\0') { // Pre-increment to skip return type.
        if (*cp == 'L') {
            method->noRef = false;
            break;
        }
    }

    DalvikBridgeFunc bridge = gDvmJni.useCheckJni ? dvmCheckCallJNIMethod : dvmCallJNIMethod;
    dvmSetNativeFunc(method, bridge, (const u2*) func);
}


这里的DalvikBridgeFunc bridge = gDvmJni.useCheckJni ? dvmCheckCallJNIMethod : dvmCallJNIMethod;是一个bridge函数,也称之为函数中转站,当调用native方法时,会通过bridge调用,由于dalvik对不同平台的支持,调用native方法为了适应多平台而采用的一种机制。

下面一段来自http://blog.csdn.net/luoshengyang/article/details/8923483
这些Bridage函数实际上仍然不是直接调用地调用JNI方法的,这是因为Dalvik虚拟机是可以运行在各种不同的平台之上,而每一种平台可能都定义有自己的一套函数调用规范,也就是所谓的ABI(Application Binary Interface),这是一个API(Application Programming Interface)不同的概念。ABI是在二进制级别上定义的一套函数调用规范,例如参数是通过寄存器来传递还是堆栈来传递,而API定义是一个应用程序编程接口规范。换句话说,API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译 ,而ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。

为了使得运行在不同平台上的Dalvik虚拟机能够以统一的方法来调用JNI方法,这些Bridage函数使用了一个libffi库,它的源代码位于external/libffi目录中。Libffi是一个开源项目,用于高级语言之间的相互调用的处理,它的实现机制可以进一步参考http://www.sourceware.org/libffi/。


我们看一下dvmCallJNIMethod函数,这个函数主要是通过
    dvmPlatformInvoke(env,
            (ClassObject*) staticMethodClass,
            method->jniArgInfo, method->insSize, modArgs, method->shorty,
            (void*) method->insns, pResult);


来对native方法调用,而dvmPlatformInvoke通过libffi进行method调用,以屏蔽Dalvik虚拟机运行在不同目标平台的细节。



回头在看一下dvmSetNativeFunc函数:
void dvmSetNativeFunc(Method* method, DalvikBridgeFunc func,
    const u2* insns)
{
   ......
    if (insns != NULL) {
        /* update both, ensuring that "insns" is observed first */
        method->insns = insns;
        android_atomic_release_store((int32_t) func,
            (volatile int32_t*)(void*) &method->nativeFunc);
    } else {
        /* only update nativeFunc */
        method->nativeFunc = func;
    }
    ......



这里主要是对注册的nativeFunc和DalvikBridgeFunc func进行一个关联,调用DalvikBridgeFunc func时,通过dvmPlatformInvoke调用nativeFunc函数。

整体jni函数注册已经分析完了,主要是处理nativefunc和bridge之间的跳转。

分享到:
评论

相关推荐

    dynamic_register_jni.zip

    动态注册的原理:JNI 允许我们提供一个函数映射表,注册给 JVM,这样 JVM 就可以用函数映射表来调用相应的函数, 而不必通过函数名来查找相关函数(这个查找效率很低,函数名超级长)流程更加清晰可控,效率更高....

    Android JNI精细化讲解,让你彻底了解JNI(中)

    本套课程共分为三部分,当前为第二部分,主要包括内容:1、JNI函数解析2、JNI类型解析3、JNI描述符(签名)解析4、JNI静态注册与动态注册原理解析5、JNI调用流程原理解析适合人群:1、有一定Android基础,零JNI基础...

    android平台sensor从底层到上层流程介绍.doc

    蓝色部分就是我们的Framework和Application了,JNI负责访问Sensor的客户端,而Application就是具体的应用程序,用来接收Sensor返回的数据,并处理实现对应的UI效果,如屏幕旋转,打电话时灭屏,自动调接背光(这三个...

    高通预览流程图

    整个流程的总结如下: -&gt;先是系统注册 CameraService 的服务 -&gt;APP 层调用 Camera.open() -&gt;Camera.java 调用 JNI native_setup() -&gt;JNI 层调用 android_hardware_Camera_native_setup -&gt; HAL 客户端(Camera.cpp)...

    Android so的热升级尝试

    在以上流程中,使用dlopen加载so之后,会继续调用JNI_Onload函数,通过系统提供的RegisterNatives函数完成一些列初始化,向虚拟机注册so库提供的JNI函数。So库也可以不实现JNI_Onload函数,而是采用自动查找的方式。...

    高通camera美颜算法接入

    整个流程的总结如下: -&gt;先是系统注册 CameraService 的服务 -&gt;APP 层调用 Camera.open() -&gt;Camera.java 调用 JNI native_setup() -&gt;JNI 层调用 android_hardware_Camera_native_setup -&gt; HAL 客户端(Camera.cpp)...

    Android开发艺术探索.任玉刚(带详细书签).pdf

    14.4 JNI调用Java方法的流程 486 第15章 Android性能优化 489 15.1 Android的性能优化方法 490 15.1.1 布局优化 490 15.1.2 绘制优化 493 15.1.3 内存泄露优化 493 15.1.4 响应速度优化和ANR日志分析 496 ...

    Android开发艺术探索

     14.4 JNI调用Java方法的流程 / 486  第15章 Android性能优化 / 489  15.1 Android的性能优化方法 / 490  15.1.1 布局优化 / 490  15.1.2 绘制优化 / 493  15.1.3 内存泄露优化 / 493  15.1.4 响应速度优化和...

    android开发艺术探索高清完整版PDF

    484 14.4 JNI调用Java方法的流程 / 486 第15章 Android性能优化 / 489 15.1 Android的性能优化方法 / 490 15.1.1 布局优化 / 490 15.1.2 绘制优化 / 493 15.1.3 内存泄露优化 / 493 15.1.4 响应速度优化和ANR...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part3

    11.7.1 注册音频设备和音频驱动312 11.7.2 在Android中使用alsa声卡313 11.7.3 在omap平台移植Android的alsa声卡驱动322 第12章 视频输出系统驱动326 12.1 视频输出系统结构326 12.2 需要移植的部分328 ...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part1

    11.7.1 注册音频设备和音频驱动312 11.7.2 在Android中使用alsa声卡313 11.7.3 在omap平台移植Android的alsa声卡驱动322 第12章 视频输出系统驱动326 12.1 视频输出系统结构326 12.2 需要移植的部分328 ...

    Android底层开发技术实战详解--内核、移植和驱动.(电子工业.王振丽).part2

    11.7.1 注册音频设备和音频驱动312 11.7.2 在Android中使用alsa声卡313 11.7.3 在omap平台移植Android的alsa声卡驱动322 第12章 视频输出系统驱动326 12.1 视频输出系统结构326 12.2 需要移植的部分328 ...

    深入理解Android:卷I--详细书签版

     全书共10章,第1章介绍了阅读本书所需要做的准备工作,主要包括对android系统架构和源码阅读方法的介绍;第2章通过对android系统中的mediascanner进行分析,详细讲解了 android中十分重要的jni技术;第3章分析了...

    java开源包1

    使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的PList类库 Blister Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用...

    JAVA上百实例源码以及开源项目

    6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...

    JAVA上百实例源码以及开源项目源代码

    EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,...

    java开源包11

    使用简便和直截了当,用户只需要加载的图片和调整帧您想要的,如位置,时间显示和处理方法前帧。 Java的PList类库 Blister Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用...

Global site tag (gtag.js) - Google Analytics