Android系统JNI的实现方式



All rights reserved

JNI(Java Native Interface)定义了一种Java代码调用C或者C++代码等其它代码的方式。

在Android系统中,JNI通过JNINativeMethod结构体进行描写叙述,该结构体定义于jni.h,例如以下所看到的:

typedef struct {
    const char* name;
    const char* signature;
    void*       fnPtr;
} JNINativeMethod;

第一个參数name:是Java代码中的函数名。

第二个參数signature:用于描写叙述函数的參数和返回值。

第三个參数fnPtr:C代码中函数的指针。

当中,第二个參数为一个描写叙述函数參数和返回值的字符串,字符串的格式例如以下:

(XX..)X

X的取值和定义例如以下所看到的:


字符


Java类型


C类型


V


void


void


Z


jboolean


unsigned char


B


jbyte


signed char


C


jchar


unsigned short


S


jshort


short


I


jint


int


J


jlong


long


F


jfloat


float


D


jdouble


double

另外,从jni.h中对于变量类型的定义中也能够看到这些字符的意义,例如以下所看到的:

typedef unsigned char   jboolean;       /* unsigned 8 bits */
typedef signed char     jbyte;          /* signed 8 bits */
typedef unsigned short  jchar;          /* unsigned 16 bits */
typedef short           jshort;         /* signed 16 bits */
typedef int             jint;           /* signed 32 bits */
typedef long long       jlong;          /* signed 64 bits */
typedef float           jfloat;         /* 32-bit IEEE 754 */
typedef double          jdouble;        /* 64-bit IEEE 754 */

typedef union jvalue {
    jboolean    z;
    jbyte       b;
    jchar       c;
    jshort      s;
    jint        i;
    jlong       j;
    jfloat      f;
    jdouble     d;
    jobject     l;
} jvalue;

比如,为一个驱动加入HAL层,并创建JNI层。仅就JNI层而言,创建frameworks/base/services/jni/com_android_server_DemoService.cpp文件,该文件里用于描写叙述JNI接口的代码例如以下所看到的:

static const JNINativeMethod method_table[] = {
                {"init_native", "()I", (void*)demo_init},
                {"setVal_native", "(II)V", (void*)demo_setVal},
                {"getVal_native", "(I)I", (void*)demo_getVal},
        };

当中“(II)V”,表示函数的有两个整形參数,返回值为void。

注意:由參数二指定的函数參数和返回值类型一定要和C函数的參数和返回值保持一致,否则尽管编译可以通过,但在Android系统载入过程中,会报例如以下所看到的的错误,导致Android系统无法正常执行。

E/dalvikvm( 1737): ERROR: couldn't find native method
E/dalvikvm( 1737): Requested: Lcom/android/server/DemoService;.init_native:()Z
E/dalvikvm( 1737): Candidate: Lcom/android/server/DemoService;.init_native:()I
E/JNIHelp ( 1737): RegisterNatives failed for 'com/android/server/DemoService', aborting
F/libc    ( 1737): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 1737 (system_server)

以上错误通发生在frameworks/base/services/jni/onload.cpp文件里的JNI_OnLoad()函数中,例如以下所看到的:

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        ALOGE("GetEnv failed!");
        return result;
    }
    ALOG_ASSERT(env, "Could not retrieve the env!");
    ……
    <strong>register_android_server_DemoService(env);</strong>
    ……
    return JNI_VERSION_1_4;
}

另外,ProGuard对程序的优化也可能导致上述执行错误的发生。此时,能够在makefile文件里加入“LOCAL_PROGUARD_ENABLED:=disabled”宏来关闭ProGuard的优化。

关于ProGuard,能够參考其官方站点:http://proguard.sourceforge.net/

ProGuard是一个免费的Java类文件压缩器、优化器、混淆器和预校验器。它会检測并删除没实用到的类、域、方法以及属性。它最大限度的优化字节码而且删除没用的指令。它用非常短的没有意义的名字对剩余的类、域和方法进行重命名。最后,它对处理过的代码进行预校验。

ProGuard的一些用途例如以下:

A.为了更小的代码档案、更快的网络传输、更快的载入速度和更小的内存占用创建更紧凑的代码;

B.使程序和库难于进行反向project;

C.列出死代码,这样就能将其删除;

D.为Java 6或更高的版本号对存在的类文件进行重定位和预校验,以充分利用其高速载入类的性能。

时间: 2024-08-25 18:02:50

Android系统JNI的实现方式的相关文章

深入浅出 - Android系统移植与平台开发(十二)- Android JNI机制

第五章.JNI机制 4.1 JNI概述 由前面基础知识可知,Android的应用层由Java语言编写,Framework框架层则是由Java代码与C/C++语言实现,之所以由两种不同的语言组合开发框架层,是由于Java代码是与硬件环境彻底"隔离"的跨平台语言,Java代码无法直接操作硬件. 比方:Android系统支持大量传感器.Java运行在虚拟机中,无法直接得到传感器数据.而Android系统基于Linux操作系统.在Linux操作系统中C/C++通过Linux提供的系统调用接口能

Android系统从驱动到上层服务再到应用的两种服务架构方式

Android系统从驱动到上层服务再到应用的两种服务架构方式 1)使用类似sensor service的方式: 此方式用于,service的接口不想暴露给上层activity直接使用的情形例如sensor架构c/s结构,适合多个应用与单个服务通信,binder通信时,做connection的区分即可区分不同的client. 2)使用AIDL直接暴露接口的方式: 这个更适合单个应用与服务通信,多个应用与服务通信时,需要处理接口的重入问题.利用Binder实现的标准JNI,不用你去专门实现自己的JN

OpenCV4Android释疑: 透析Android以JNI调OpenCV的三种方式(让OpenCVManager永不困扰)

前文曾具体探讨了关于OpenCV的使用,原本以为天下已太平.但不断有人反应依旧配不好OpenCV4Android,不能得心应手的在Android上使用OpenCV.大量的精力都浪费在摸索配置上.尤其是OpenCVManager诞生之后.更让人无语.大家第一个反应就是怎样才干不安装OpenCVManager.由于要多安装这个东西对客户来说体验太不好了. 咱家昨夜研究至两点,今早七点起床.最终把头绪理清了. 以下咱家以之前做过的一个基于OpenCV2.3.1.android通过jni调用opencv

Android系统关机或重启的几种实现方式

前阵子工作上遇到一些关于Android系统关机或重启的系统修改,于是,做了一些尝试,也搜集了一下资料,现在整理一下,做一些总结,方便学习或者日后工作的需要. 默认的SDK并没有提供应用开发者直接的Android系统关机或重启的API接口,一般来讲,实现Android系统的关机或重启,需要较高的权限(系统权限甚至Root权限).所以,在一般的APP中,如果想要实现关机或重启功能,要么是在App中声明系统权限,要么是通过某种“间接”的方式,比如广播或反射,来间接实现系统关机或重启.再者,就是放在源码

Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码)

一.前言 今天我们继续来看破解apk的相关知识,在前一篇:Eclipse动态调试smali源码破解apk 我们今天主要来看如何使用IDA来调试Android中的native源码,因为现在一些app,为了安全或者效率问题,会把一些重要的功能放到native层,那么这样一来,我们前篇说到的Eclipse调试smali源码就显得很无力了,因为核心的都在native层,Android中一般native层使用的是so库文件,所以我们这篇就来介绍如何调试so文件的内容,从而让我们破解成功率达到更高的一层.

Android 随想录之 Android 系统架构

应用层(Application) Android 的应用层由运行在 Android 设备上的所有应用程序共同构成(系统预装程序以及第三方应用程序). 系统预装应用程序包含拨号软件.短信.联系人.邮件客户端.日历.地图以及浏览器等提供基础功能的应用程序构成.第三方应用程序则是基于 Android SDK(Android Software Development Kit)进行开发,并受到框架层 SDK 接口约束的应用程序.两者的区别在于,系统预装应用比第三方应用拥有更高的系统使用权限:系统预装应用可

Android技术19:Android系统架构

Android系统架构是学习Android最基本的知识点,经常在技术面试过程中涉及到有关问题,接下来对Android系统架构进行总结. Android官方文档提供资料显示:Android系统分为4个层次,从低到高依次为Linux kernel(Linux内核层),Libraries和Android运行时Runtime,Android Framework,Applications. 1.Applications应用层 该层主要是运行在Andorid系统上的应用程序,如Home,SMS,Contac

Android中JNI的使用

Android中JNI编程的那些事儿 首先说明,Android系统不允许一个纯粹使用C/C++的程序出现,它要求必须是通过Java代码嵌入Native C/C++——即通过JNI的方式来使用本地(Native)代码.因此JNI对Android底层开发人员非常重要. 如何将.so文件打包到.APK 让我们 先 从最简单的情况开始,假如已有一个JNI实现——libxxx.so文件,那么如何在APK中使用它呢? 在我最初写类似程序的时候,我会将libxxx.so文件push到/system/lib/目

Android系统以及Activity启动讲解

一.Android系统启动 Android框架架构图:(来自网上,我觉得这张图看起来很清晰) Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用.启动的过程如下图所示:(图片来自网上,后面有地址) Android系统整个过程如下: (一) Init进程的启动 init进程,它是一个由内核启动的用户级进程.内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程.init