2010年11月04日
DalvikVMのJITのON/OFFに関するTips
DalvikVMのJITのON/OFFについて少し調べました。
- JITが使えるようにビルドされているかどうか確認する方法
- JITをオフにして動かす方法
- アプリごとにJITをオフにする方法
- システム全体でJITをオフにする方法
JITが使えるようにビルドされているかどうか確認する方法
具体的にはWITH_JITが定義されている状態でビルドされたかどうかということになります。
シリアルコンソールかadb shellで dalvikvm -help として、最後のほうに出てくるConfigured with: の行でjitと出るかどうかでわかります。
以下はWITH_JITが定義されている状態の実行結果です。
# dalvikvm -help dalvikvm: [options] class [argument ...] dalvikvm: [options] -jar file.jar [argument ...] ... -Xjitverbose -Xjitprofile -Xjitdisableopt Configured with: debugger profiler hprof jit show_exception=1 Dalvik VM init failed (check log file) #
ここの部分のソースコードは以下のようになっています。JIT以外にもいろいろなコンフィグがあるのがわかります。
dalvik/vm/Init.c
dvmFprintf(stderr, "\n"); dvmFprintf(stderr, "Configured with:" #ifdef WITH_DEBUGGER " debugger" #endif #ifdef WITH_PROFILER " profiler" #endif #ifdef WITH_MONITOR_TRACKING " monitor_tracking" #endif #ifdef WITH_DEADLOCK_PREDICTION " deadlock_prediction" #endif #ifdef WITH_HPROF " hprof" #endif #ifdef WITH_HPROF_STACK " hprof_stack" #endif #ifdef WITH_HPROF_STACK_UNREACHABLE " hprof_stack_unreachable" #endif #ifdef WITH_ALLOC_LIMITS " alloc_limits" #endif #ifdef WITH_TRACKREF_CHECKS " trackref_checks" #endif #ifdef WITH_INSTR_CHECKS " instr_checks" #endif #ifdef WITH_EXTRA_OBJECT_VALIDATION " extra_object_validation" #endif #ifdef WITH_EXTRA_GC_CHECKS " extra_gc_checks" #endif #ifdef WITH_DALVIK_ASSERT " dalvik_assert" #endif #ifdef WITH_JNI_STACK_CHECK " jni_stack_check" #endif #ifdef EASY_GDB " easy_gdb" #endif #ifdef CHECK_MUTEX " check_mutex" #endif #ifdef PROFILE_FIELD_ACCESS " profile_field_access" #endif #ifdef DVM_TRACK_HEAP_MARKING " track_heap_marking" #endif #if DVM_RESOLVER_CACHE == DVM_RC_REDUCING " resolver_cache_reducing" #elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING " resolver_cache_expanding" #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE " resolver_cache_disabled" #endif #if defined(WITH_JIT) " jit" #endif #if defined(WITH_SELF_VERIFICATION) " self_verification" #endif );
JITが有効になっている時には、Androidアプリケーションのプロセスに "Compiler"という名前のスレッドが生成されるので、それをデバッガやDDMSで調べるという方法もあります。
JITをOFFにして動かす方法
JITの効果を比較して確認したいときや、もしかしてJITのバグかも?と思う時にJITをOFFにして動かしたいということがあります。
JITをOFFにするためにはZygoteに与えるdebugFlagsでDEBUG_ENABLE_SAFEMODEのビットを立てます。それは以下の部分のソースで行っています。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
// Run the app in safe mode if its manifest requests so or the // system is booted in safe mode. if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || Zygote.systemInSafeMode == true) { debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; }
アプリごとにJITをオフにする方法
Androidでアプリのマニフェストでandroid:vmSafeModeをTRUEにするとJITを無効にできます。
システム全体でJITをオフにする方法
起動するときにMENUキーかキーボードの's'キーをずっと押し続けるとシステム全体がSafe modeになり、JITが無効になります。
その部分は以下のソースで行っています。
frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java
public boolean detectSafeMode() { try { int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU); int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S); int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER); int trackballState = mWindowManager.getTrackballScancodeState(RawInputEvent.BTN_MOUSE); mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0; performHapticFeedbackLw(null, mSafeMode ? HapticFeedbackConstants.SAFE_MODE_ENABLED : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); if (mSafeMode) { Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState + " dpad=" + dpadState + " trackball=" + trackballState + ")"); } else { Log.i(TAG, "SAFE MODE not enabled"); } return mSafeMode; } catch (RemoteException e) { // Doom! (it's also local) throw new RuntimeException("window manager dead"); } }
うまくセーフモードになった時のlogcatのログ。
I/WindowManager( 897): SAFE MODE ENABLED (menu=0 s=1 dpad=0 trackball=0)
また、この時にはLCD画面の左下に"Safe mode"と表示されます。
通常の場合のlogcatのログ。
I/WindowManager( 900): SAFE MODE not enabled D/dalvikvm( 900): JIT started for system_server