zoukankan      html  css  js  c++  java
  • Android系统JNI的实现方式

    

    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或更高的版本号对存在的类文件进行重定位和预校验,以充分利用其高速载入类的性能。




















  • 相关阅读:
    程序员练手项目
    文件描述符
    安卓深度探索(卷一)第九章
    安卓深度探索(卷一)第十章
    安卓深度探索(卷一)第八章
    安卓深度探索(卷一)第六章
    安卓深度探索(卷一)第七章
    安卓深度探索(卷一)第五章
    记一次联想A820t救砖线刷
    记一次酷派尚锋Y75刷机
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4222224.html
Copyright © 2011-2022 走看看