android之看"马达"如何贯通android系统,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!");

……

register_android_server_DemoService(env);

……

return JNI_VERSION_1_4;

}

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

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

ProGuard的一些用途例如以下:

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值