Implementation of JNI in Android system
Zookeeper
Implementation of JNI in Android system
All rights reserved
JNI (Java Native Interface) defines a method for Java code to call other Code such as C or C ++ code.
In Android, JNI is described through the JNINativeMethod struct, which is defined in jni. h as follows:
typedef struct { const char* name; const char* signature; void* fnPtr;} JNINativeMethod;
The first parameter name is the function name in Java code.
The second parameter signature is used to describe the parameters and return values of a function.
The third parameter fnPtr is the pointer of the function in C code.
The second parameter is a string that describes the function parameters and return values. The format of the string is as follows:
(XX...) X
The value and definition of X are as follows:
Character |
Java type |
C type |
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 |
In addition, the meaning of these characters can also be seen from the definition of the variable type in jni. h, as shown below:
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;
For example, add a HAL layer to a driver and create a JNI layer. For the JNI layer only, create the frameworks/base/services/jni/com_android_server_DemoService.cpp file. The code used to describe the JNI interface is as follows:
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" indicates that the function has two integer parameters, and the return value is void.
Note: The function parameters and return value types specified by parameter 2 must be consistent with the C function parameters and return values. Otherwise, although compilation can pass, during the Android system loading process, the following error is reported, causing the Android system to fail.
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)
The above error occurs in the JNI_OnLoad () function in the frameworks/base/services/jni/onload. cpp file, as shown below:
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;}
In addition, ProGuard program optimization may also lead to the above running errors. In this case, you can add the "LOCAL_PROGUARD_ENABLED: = disabled" macro to the makefile file to disable ProGuard optimization.
For ProGuard, refer to its official website: http://proguard.sourceforge.net/
ProGuard is a free Java class file compressors, optimizer, obfuscators, and pre-validators. It detects and deletes unused classes, fields, methods, and attributes. It optimizes bytecode to the maximum extent and deletes useless commands. It renames the remaining classes, fields, and methods with a very short meaningless name. Finally, it performs pre-verification on the processed code.
ProGuard has the following functions:
A. Create more compact code for smaller code files, Faster network transmission, faster loading speed, and smaller memory usage;
B. Make reverse engineering difficult for programs and libraries;
C. List dead code so that it can be deleted;
D. relocate and pre-validate existing class files for Java 6 or later versions to make full use of the class loading performance.