Controlling the Embedded VM


The Dalvik VM supports a variety of command-line arguments (use adb shell dalvikvm -help to get a summary), but it's not possible to pass arbitrary arguments through the Android application runtime. It is, however, possible to affect the VM behavior through certain system properties.

For all of the features described below, you would set the system property with setprop, issuing a shell command on the device like this:

adb shell setprop <name> <value>

The Android runtime must be restarted before the changes will take effect (adb shell stop; adb shell start). This is because the settings are processed in the "zygote" process, which starts early and stays around "forever".

You could also add a line to /data/local.prop that looks like:

<name> = <value>

Such changes will survive reboots, but will be removed by anything that wipes the data partition. (Hint: create a local.prop on your workstation, then adb push local.prop /data .)

Extended JNI Checks

JNI, the Java Native Interface, provides a way for code written in the Java programming language interact with native (C/C++) code. The extended JNI checks will cause the system to run more slowly, but they can spot a variety of nasty bugs before they have a chance to cause problems.

There are two system properties that affect this feature, which is enabled with the -Xcheck:jni command-line argument. The first is This is set by the Android build system for development builds. (It may also be set by the Android emulator unless the -nojni flag is provided on the emulator command line.) Because this is an "ro." property, the value cannot be changed once the device has started.

To allow toggling of the CheckJNI flag, a second property, dalvik.vm.checkjni, is also checked. The value of this overrides the value from

If neither property is defined, or dalvik.vm.checkjni is set to false, the -Xcheck:jni flag is not passed in, and JNI checks will be disabled.

To enable JNI checking:

adb shell setprop dalvik.vm.checkjni true

For more information about JNI checks, see JNI Tips.


Dalvik VM supports the Java programming language "assert" statement. By default they are off, but the dalvik.vm.enableassertions property provides a way to set the value for a -ea argument.

The argument behaves the same as it does in other desktop VMs. You can provide a class name, a package name (followed by "..."), or the special value "all".

For example, this:

adb shell setprop dalvik.vm.enableassertions all
enables assertions in all non-system classes.

The system property is much more limited than the full command line. It is not possible to specify more than one -ea entry, and there is no way to specify a -da entry. There is presently no equivalent for -esa/-dsa.

Bytecode Verification and Optimization

The system tries to pre-verify all classes in a DEX file to reduce class load overhead, and performs a series of optimizations to improve runtime performance. Both of these are done by the dexopt command, either in the build system or by the installer. On a development device, dexopt may be run the first time a DEX file is used and whenever it or one of its dependencies is updated ("just-in-time" optimization and verification).

There are two command-line flags that control the just-in-time verification and optimization, -Xverify and -Xdexopt. The Android framework configures these based on the dalvik.vm.verify-bytecode property.

If you set:

adb shell setprop dalvik.vm.verify-bytecode true
then the framework will pass -Xverify:all -Xdexopt:verified to the VM. This enables verification, and only optimizes classes that successfully verified. This is the safest setting, and is the default.

If dalvik.vm.verify-bytecode is set to false, the framework passes -Xverify:none -Xdexopt:verified to disable verification. (We could pass in -Xdexopt:all, but that wouldn't necessarily optimize more of the code, since classes that fail verification may well be skipped by the optimizer for the same reasons.) Classes will not be verified by dexopt, and unverified code will be loaded and executed.

Enabling verification will make the dexopt command take significantly longer, because the verification process is fairly slow. Once the verified and optimized DEX files have been prepared, verification incurs no additional overhead except when loading classes that failed to pre-verify.

If your DEX files are processed with verification disabled, and you later turn the verifier on, application loading will be noticeably slower (perhaps 40% or more) as classes are verified on first use.

For best results you should force a re-dexopt of all DEX files when this property changes. You can do this with:

adb shell "rm /data/dalvik-cache/*"
This removes the cached versions of the DEX files. Remember to stop and restart the runtime (adb shell stop; adb shell start).

Execution Mode

The current implementation of the Dalvik VM includes three distinct interpreter cores. These are referred to as "fast", "portable", and "debug". The "fast" interpreter is optimized for the current platform, and might consist of hand-optimized assembly routines. In constrast, the "portable" interpreter is written in C and expected to run on a broad range of platforms. The "debug" interpreter is a variant of "portable" that includes support for profiling and single-stepping.

The VM allows you to choose between "fast" and "portable" with an extended form of the -Xint argument. The value of this argument can be set through the dalvik.vm.execution-mode system property.

To select the "portable" interpreter, you would use:

adb shell setprop dalvik.vm.execution-mode int:portable
If the property is not specified, the most appropriate interpreter will be selected automatically. At some point this mechanism may allow selection of other modes, such as JIT compilation.

Not all platforms have an optimized implementation. In such cases, the "fast" interpreter is generated as a series of C stubs, and the result will be slower than the "portable" version. (When we have optimized versions for all popular architectures the naming convention will be more accurate.)

If profiling is enabled or a debugger is attached, the VM switches to the "debug" interpreter. When profiling ends or the debugger disconnects, the original interpreter is resumed. (The "debug" interpreter is substantially slower, something to keep in mind when evaluating profiling data.)

Deadlock Prediction

If the VM is built with WITH_DEADLOCK_PREDICTION, the deadlock predictor can be enabled with the -Xdeadlockpredict argument. (The output from dalvikvm -help will tell you if the VM was built appropriately -- look for deadlock_prediction on the Configured with: line.) This feature tells the VM to keep track of the order in which object monitor locks are acquired. If the program attempts to acquire a set of locks in a different order from what was seen earlier, the VM logs a warning and optionally throws an exception.

The command-line argument is set based on the dalvik.vm.deadlock-predict property. Valid values are off to disable it (default), warn to log the problem but continue executing, err to cause a dalvik.system.PotentialDeadlockError to be thrown from the monitor-enter instruction, and abort to have the entire VM abort.

You will usually want to use:

adb shell setprop dalvik.vm.deadlock-predict err
unless you are keeping an eye on the logs as they scroll by.

Please note that this feature is deadlock prediction, not deadlock detection -- in the current implementation, the computations are performed after the lock is acquired (this simplifies the code, reducing the overhead added to every mutex operation). You can spot a deadlock in a hung process by sending a kill -3 and examining the stack trace written to the log.

This only takes monitors into account. Native mutexes and other resources can also be the cause of deadlocks.

Stack Dumps

Like other desktop VMs, when the Dalvik VM receives a SIGQUIT (Ctrl-\ or kill -3), it dumps stack traces for all threads. By default this goes to the Android log, but it can also be written to a file.

The dalvik.vm.stack-trace-file property allows you to specify the name of the file where the thread stack traces will be written. The file will be created (world writable) if it doesn't exist, and the new information will be appended to the end of the file. The filename is passed into the VM via the -Xstacktracefile argument.

For example:

adb shell setprop dalvik.vm.stack-trace-file /tmp/stack-traces.txt

If the property is not defined, the VM will write the stack traces to the Android log when the signal arrives.

Copyright © 2008 The Android Open Source Project