Dalvik VM 有一個控制參數: checkjni
因為 jni code 比較難 debug,還有一旦出問題,就會造成整個 vm crash.
所以 android 提供一個 switch, 讓 user 決定是不是要啟動 dalvik 對 jni 的安全檢查。
ro.kernel.android.checkjni
這個 option 在 build eng type 的 image 時,會被加進 build.prop
framework 中參考這個 option 是在:framework/base/core/jni/AndroidRuntime.cpp:
property_get("dalvik.vm.checkjni", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
checkJni = true;
} else if (strcmp(propBuf, "false") != 0) {
/* property is neither true nor false; fall back on kernel parameter */
property_get("ro.kernel.android.checkjni", propBuf, "");
if (propBuf[0] == '1') {
checkJni = true;
}
}
所以在 init.rc 中加上
setprop dalvik.vm.checkjni false
也可以。
在 dalvik 的 source code 中。
vm/Jni.c:
} else if (strcmp(optStr, "-Xcheck:jni") == 0) {
checkJni = true;
} else if (strncmp(optStr, "-Xjniopts:", 10) == 0) {
...
if (checkJni) {
dvmUseCheckedJniVm(pVM);
pVM->useChecked = true;
}
...
if (vm->useChecked)
dvmUseCheckedJniEnv(newEnv);
也就是說,一旦 enable check:jni..
vm 就會..
vm/CheckJni.c
void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
{
assert(pEnv->funcTable != &gCheckNativeInterface);
pEnv->baseFuncTable = pEnv->funcTable;
pEnv->funcTable = &gCheckNativeInterface;
}
其中,gCheckNativeInterface 就是一些 check function..
static const struct JNINativeInterface gCheckNativeInterface = {
NULL,
NULL,
NULL,
NULL,
Check_GetVersion,
Check_DefineClass,
Check_FindClass,
Check_FromReflectedMethod,
Check_FromReflectedField,
Check_ToReflectedMethod,
Check_GetSuperclass,
Check_IsAssignableFrom,
Check_ToReflectedField,
...
...
其中的一個,checkUtfString, 就是檢查 passing throught 的 string 是不是符合 modified utf 的格式。
/*
* Verify that "bytes" points to valid "modified UTF-8" data.
*/
static void checkUtfString(JNIEnv* env, const char* bytes, bool nullOk,
const char* func)
{
const char* origBytes = bytes;
...
...
while (*bytes != '\0') {
u1 utf8 = *(bytes++);
// Switch on the high four bits.
switch (utf8 >> 4) {
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07: {
// Bit pattern 0xxx. No need for any extra bytes.
break;
}
.,,,
這個 function check fail 的話,在logcat 就會出現:
W/dalvikvm( 1044): JNI WARNING: illegal start byte 0xa6
W/dalvikvm( 1044): string: '米??007亞洲初登場超級紀念盤 Disc 2'
W/dalvikvm( 1044): in Landroid/media/MediaScanner;.processFile (Ljava/lang/String;Ljava
/lang/String;Landroid/media/MediaScannerClient;)V (NewStringUTF)
..
ref: