Camera Java Native Interface(JNI)介绍

Java Native Interface(JNI)概述

Android系统按语言来划分由两个世界组成,分别是Java世界和Native世界。JNI就是为了解决当应用程序不能完全用Java编写时所需要的工具。因为在Java诞生之前,就有很多程序和库都是由Native语言写的。为了更好的复用之前native语言写的库所以设计出这套interface,JNI相当于链接两个世界的纽带。
JNI Layer
以下为JNI设计历史,有兴趣可以去reference中查看:
The following examples illustrate when you need to use Java native methods:

  • The standard Java class library does not support theplatform-dependent features needed by the application.
  • You already have a library written in another language, and wish to make it accessible to Java code through the JNI.
  • You want to implement a small portion of time-critical code in a lower-level language such as assembly.

By programming through the JNI, you can use native methods to:

  • Create, inspect, and update Java objects (including arrays and strings).
  • Call Java methods.
  • Catch and throw exceptions.
  • Load classes and obtain class information.
  • Perform runtime type checking.

You can also use the JNI with the Invocation API to enable an arbitrary native application to embed the Java VM. This allows programmers to easily make their existing applications Java-enabled without having to link with the VM source code.

在历史问题下,一开始主要有三种native method interface:JDK 1.0 native method interface;Netscape’s Java Runtime Interface;Microsoft’s Raw Native Interface and Java/COM interface。但是对于produce, maintain, and distribute非常的不友好。

Our Goal

We(oracle?)believe that a uniform, well-thought-out standard interface offers the following benefits for everyone:

  • Each VM vendor can support a larger body of native code.
  • Tool builders will not have to maintain different kinds of native method interfaces.
  • Application programmers will be able to write one version of their native code and this version will run on different VMs.

统一的interface有很多好处,大家一起商量来统一,并且至少要满足以下要求:

  • Binary compatibility - The primary goal is binary compatibility of native method libraries across all Java VM implementations on a given platform. Programmers should maintain only one version of their native method libraries for a given platform.
  • Efficiency - To support time-critical code, the native method interface must impose little overhead. All known techniques to ensure VM-independence (and thus binary compatibility) carry a certain amount of overhead. We must somehow strike a compromise between efficiency and VM-independence.
  • Functionality - The interface must expose enough Java VM internals to allow native methods to accomplish useful tasks.

但是之前主要流行的三种native method interface都有各自的问题,无法满足完整的要求,所以只能重新设计一套。

一、JNI启动流程

Android系统在启动的过程中,先启动Kernel创建init进程,紧接着由init进程fork第一个横穿Java和C/C++的进程,即Zygote进程。
Zygote启动过程会在 AndroidRuntime.cpp 中的startVM创建虚拟机,VM创建完成后,App 进程启动流程中,紧接着调用 startReg 完成虚拟机中的JNI方法注册。

  1. Android Runtime
/*
 1. Start the Android runtime.  This involves starting the virtual machine
 2. and calling the "static void main(String[] args)" method in the class
 3. named by "className".
 4.  5. Passes the main function two arguments, the class name and the specified
 5. options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
	...
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    //注册env之后,通过env启动main方法
	...
}
  1. Start Reg
/*
 7. Register android native functions with the VM.
 */
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
	...
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
        env->PopLocalFrame(NULL);
        return -1;
    }
    env->PopLocalFrame(NULL);
    return 0;
}
  1. register_jni_procs
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
            ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
            return -1;
        }
    }
    return 0;
}

register_jni_procs function循环调用gRegJNI数组成员所对应的方法

  1. gRegJNI数组
static const RegJNIRec gRegJNI[] = {
...
REG_JNI(register_android_hardware_Camera),
...
}

gRegJNI数组,有138个成员变量,数组中每一个成员都代表一类文件的jni映射,其中REG_JNI是一个宏定义,

  1. REG_JNI宏定义
#define REG_JNI(name)      { name, #name }
struct RegJNIRec {
    int (*mProc)(JNIEnv*);
    const char* mName;
};

其中 mProc,就等价于调用其参数名所指向的函数,例如REG_JNI(register_android_hardware_Camera).mProc(env),也就是进入register_android_hardware_Camera的方法,进入此方法的意义在后文解释。

二、Camera JNI 动态注册

代码如下(示例):

//gMethods:java层方法名与jni层的方法的一一映射关系
static const JNINativeMethod camMethods[] = {
  { "_getNumberOfCameras",
    "()I",
    (void *)android_hardware_Camera_getNumberOfCameras },
  { "_getCameraInfo",
    "(ILandroid/hardware/Camera$CameraInfo;)V",
    (void*)android_hardware_Camera_getCameraInfo },
  { "native_setup",
    "(Ljava/lang/Object;ILjava/lang/String;)I",
    (void*)android_hardware_Camera_native_setup },
}

// Get all the required offsets in java class and register native functions
int register_android_hardware_Camera(JNIEnv *env)
{
	...
    // Register native functions
    return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods));
}

所以当REG_JNI(register_android_hardware_Camera).mProc(env)在调用的时候才能进入到对应register_android_hardware_Camera function方法体中。
register_android_hardware_Camera function register native function ,建立java对jni方法的映射关系,调用java方法native_setup才能调用到android_hardware_Camera_native_setup native method,进入到JNI Layer进行处理。

Reference

blog

链接: Oracle JNI Introduction
链接: 关于"JNI"的那些事

Code Address:

  • frameworks/base/core/jni/AndroidRuntime.cpp
  • frameworks/base/core/jni/android_hardware_Camera.cpp
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值