Will my Android App still run with ART instead of Dalvik?


With Android L, the virtual machine compiler will move to ART (Android RunTime) and only ART for 64 bit. So what do we know about ART vs Dalvik and what does it mean for App code?

ART is an  AOT (ahead of time) compiler meaning that dex2oat runs once, during the initial installation of the app. Dalvik was a JIT (just in time) compiler that ran only as the app was called.  In trade for a longer app installation time, ART frees up the processor later when the app is called.  Additionally a new garbage collector and memory allocators will reduce the number and duration of pauses meaning ART provides better responsiveness and less power draw.  But remember, the smaller memory footprint at runtime also means increased storage needs for the compiled binaries.   ART will work with ARM, x86, and MIPS hardware and show definite improvement running floating point calculations. 

So what changes to coding? Well, the good news is that ART is backward compatible, using the Dex (Dalvik executable) byte code format. So most apps should just run (and even run better). 

However, there are some things to be checked and optimizations that may be available:

  1. Check for ART by the value returned from  System.getProperty("java.vm.version"). ART is "2.0.0" or higher.
  2. If you use JNI to run C/C++ code, be sure to use CheckJNI (set debuggable="true" in the manifest).  See Debugging Android JNI with CheckJNI  (Note: this setting is for prerelease debugging and should not be set to true in the released code). 
  3. Get the latest versions of tools. ART does tighter bytecode verification at install time than Dalvik did. Code produced by the Android build tools should work but some post-processing tools (especially obfuscation tools) may produce invalid files (ok in Dalvik but rejected by ART.)

  4. Consider whether to remove some of the exception checks (which should no longer be needed since ART sees the whole code at once, but remembering that Dalvik will be around for some time.) 

  5. Remove most System.gc() calls, especially those for reducing GC_FOR_ALLOC-type occurrences or fragmentation.

  6. Don't save pointers to object instance data and don't pass a modified pointer to Release...ArrayElements()   The compacting garbage collector (already in AOSP) may move objects into memory and Get and Release calls to ArrayElements() could corrupt memory. If you make any changes to the returned array elements, you must call the appropriate function: 
    • No changes made to array > use JNI_ABORT mode, (release memory, no copy back).
    • Change(s) made, but don't need to reference them > use code 0 ( updates the array object and frees the copy).
    • Changes made and Need to commit  them >  use JNI_COMMIT (which updates the underlying array object and retains the copy).
  7. Don't attempt to look at the fields of  Object, since it now has private fields. When iterating up a class hierarchy as part of a serialization framework, stop when Class.getSuperclass()==java.lang.Object.class (don't continue until null is returned.) 
  8. Use the additional error handling  and logging in ART
    • Improved throwing and logging of NoSuchMethodError: from GetMethodID() and GetStaticMethodID()  and from 
      RegisterNatives call  (caused pehaps because the method was removed by a tool such as ProGuard)

    • A  NoSuchFieldError (instead of null) from  GetFieldID() and GetStaticFieldID() 

    • A warning when subclasses try to override package-private methods.To override a class's method, declare the method as public or protected.

    • Other problems that are flagged by the ART verifier include:
      • invalid control flow
      • unbalanced moniterenter/monitorexit
      • 0-length parameter type list size
  9. ​​Pay attention to the stricter JNI spec enforcement including that CallNonvirtual---Method() methods require the method to declare a class, not a subclass.  

  10. Watch the size of the ART unified Thread stack which should be about equal to the two Dalvik stacks (by default a 32 KB Java stack and a 1 MB native stack). Anywhere that the stack size is explicitly set needs to be checked - including Java calls to the Thread constructor including a size increase if StackOverflowError occurs.

  11. Watch pthread size (pthreat_attr_setstack() and pthreat_attr_setstacksize()as calls including AttachCurrentThread() will throw an error.

  12. Remove any dependencies on the installed .odex file format in /system/framework/data/dalvik-cache, or in DexClassLoader’s optimized output directory. While ART tries to follow the same naming and locking rules in ELF, apps should not depend on the file format. 

  13. Use the latest Mockito to correctly have Proxy InvocationHandler.invoke() receive null (instead of an empty array), if there are no arguments.

  14. Check any notifications you send. There's a new color scheme in Android L.

    • Use android.app.Norification.Builder.setColor() to set an accent color in a circle behind your icon image.
    • Remember to only use alpha only channels for the main notification icon and action icons
    • Check Heads up notifications (Those using fullScreenIntent, or high priority notifications with ringtone/vibrations)


Verifying App Behavior on the Android Runtime (ART)     




For more complete information about compiler optimizations, see our Optimization Notice.