Android系統JNI的實現方式,androidjni實現

來源:互聯網
上載者:User

Android系統JNI的實現方式,androidjni實現


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 methodE/dalvikvm( 1737): Requested: Lcom/android/server/DemoService;.init_native:()ZE/dalvikvm( 1737): Candidate: Lcom/android/server/DemoService;.init_native:()IE/JNIHelp ( 1737): RegisterNatives failed for 'com/android/server/DemoService', abortingF/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.使程式和庫難於進行反向工程;

C.列出無作用程式碼,這樣就能將其刪除;

D.為Java 6或更高的版本對存在的類檔案進行重定位和預校正,以充分利用其快速載入類的效能。




















聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.