Home | History | Annotate | Download | only in practices
      1 page.title=Verifying App Behavior on the Android Runtime (ART)
      2 @jd:body
      3 
      4 <div id="qv-wrapper">
      5 <div id="qv">
      6 <h2>Quickview</h2>
      7   <ul>
      8     <li>The new Android runtime (ART) is available on some of the newest Android
      9       devices, though all of them currently have Dalvik as the default
     10       runtime.</li>
     11     <li>App developers should make sure their apps are compatible with ART,
     12       especially if you use JNI to run native code or if you use certain tools
     13       that produce non-standard code (such as some obfuscators).</li>
     14   </ul>
     15 
     16   <h2 id="Contents">In this document</h2>
     17  <ol>
     18     <li><a href="#GC_Migration">Addressing Garbage Collection (GC) Issues</a></li>
     19     <li><a href="#JNI_Issues">Preventing JNI Issues</a>
     20       <ol>
     21         <li><a href="#JNI_and_GC">Checking JNI code for garbage-collection
     22           issues</a></li>
     23         <li><a href="#Error_Handling">Error handling</a></li>
     24         <li><a href="#Object_Model_Changes">Object model changes</a></li>
     25       </ol>
     26     </li>
     27     <li><a href="#Stack_Size">Preventing Stack Size Issues</a></li>
     28     <li><a href="#AOT_Fails">Fixing AOT Compilation Issues</a></li>
     29     <li><a href="#Reporting_Problems">Reporting Problems</a></li>
     30   </ol>
     31   <h2>See also</h2>
     32   <ol>
     33     <li><a href="http://source.android.com/devices/tech/dalvik/art.html">Introducing ART</a></li>
     34     <li><a
     35 href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html">Debugging
     36 Android JNI with CheckJNI</a></li>
     37   </ol>
     38 </div>
     39 </div>
     40 
     41 <p>With Android 4.4, we are beginning to roll out a new Android runtime,
     42 <strong>ART</strong>. This runtime offers a number of new features that improve
     43 performance and smoothness of the Android platform and apps. (You can find more
     44 information about ART's new features in <a
     45 href="http://source.android.com/devices/tech/dalvik/art.html">Introducing
     46 ART</a>.)</p>
     47 
     48 <p>Currently, ART is available on a number of Android 4.4 devices, such as the
     49 Nexus 4, Nexus 5, Nexus 7, and Google Play edition devices.
     50 At this time, all devices still use Dalvik as the default runtime. We encourage
     51 you to test your apps for ART compatibility and to take advantage of ART's new
     52 features. However, for the time being, you should also take care to maintain
     53 compatibility with Dalvik.</p>
     54 
     55 <p>This document lets you know about things to watch for when migrating an
     56 existing app to be compatible with ART. Most apps should just work when
     57 running with ART. However, some techniques that work on Dalvik do not work on
     58 ART. This document discusses some of these issues.</p>
     59 
     60 <h2 id="GC_Migration">Addressing Garbage Collection (GC) Issues</h2>
     61 
     62 <p>Under Dalvik, apps frequently find it useful to explicitly call {@link
     63 java.lang.System#gc() System.gc()} to prompt garbage collection (GC). This should be
     64 far less necessary with ART, particularly if you're invoking garbage collection
     65 to prevent <a
     66 href="{@docRoot}/tools/debugging/debugging-memory.html#LogMessages"><code>GC_FOR_ALLOC</code></a>-type
     67 occurrences or to reduce fragmentation. You can verify which runtime is in use
     68 by calling {@link java.lang.System#getProperty(java.lang.String)
     69 System.getProperty("java.vm.version")}. If ART is in use, the property's value
     70 is <code>"2.0.0"</code> or higher.</p>
     71 
     72 <p>Furthermore, a compacting garbage collector is under development in the <a
     73 href="https://source.android.com">Android Open-Source Project (AOSP)</a> to
     74 improve memory management. Because of this, you should avoid using techniques
     75 that are incompatible with compacting GC (such as saving pointers to object
     76 instance data). This is particularly important for apps that make use of the
     77 Java Native Interface (JNI). For more information, see <a
     78 href="#JNI_Issues">Preventing JNI Issues</a>.</p>
     79 
     80 <h2 id="JNI_Issues">Preventing JNI Issues</h2>
     81 
     82 <p>ART's JNI is somewhat stricter than Dalvik's. It is an especially good idea
     83 to use CheckJNI mode to catch common problems. If your app makes use of C/C++
     84 code, you should review the following article:</p>
     85 
     86 <p><a
     87 href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html">Debugging
     88 Android JNI with CheckJNI</a></p>
     89 
     90 <h3 id="JNI_and_GC">Checking JNI code for garbage-collection issues</h3>
     91 
     92 <p>ART has a compacting garbage collector under development on the
     93 Android Open Source Project (AOSP). Once the compacting garbage collector is in
     94 use, objects may be moved in memory. If you use C/C++ code, do not
     95 perform operations that are incompatible with compacting GC. We have enhanced
     96 CheckJNI to identify some potential issues (as described in <a
     97 href="http://android-developers.blogspot.com/2011/11/jni-local-reference-changes-in-ics.html">JNI
     98 Local Reference Changes in ICS</a>).</p>
     99 
    100 <p>One area to watch for in particular is the use of
    101 <code>Get...ArrayElements()</code> and <code>Release...ArrayElements()</code>
    102 functions. In runtimes with non-compacting GC, the
    103 <code>Get...ArrayElements()</code> functions typically return a reference to the
    104 actual memory backing the array object. If you make a change to one of the
    105 returned array elements, the array object is itself changed (and the arguments
    106 to <code>Release...ArrayElements()</code> are usually ignored). However, if
    107 compacting GC is in use, the <code>Get...ArrayElements()</code> functions may
    108 return a copy of the memory. If you misuse the reference when compacting GC is
    109 in use, this can lead to memory corruption or other problems. For example:</p>
    110 
    111 <ul>
    112 
    113   <li>If you make any changes to the returned array elements, you must call the
    114   appropriate <code>Release...ArrayElements()</code> function when you are done,
    115   to make sure the changes you made are correctly copied back to the underlying
    116   array object.</li>
    117 
    118   <li>When you release the memory array elements, you must use the appropriate
    119   mode, depending on what changes you made:
    120 
    121     <ul>
    122 
    123       <li>If you did not make any changes to the array elements, use
    124       <code>JNI_ABORT</code> mode, which releases the memory without copying
    125       changes back to the underlying array object.</li>
    126 
    127       <li>If you made changes to the array, and do not need the reference any
    128       more, use code <code>0</code> (which updates the array object and frees
    129       the copy of the memory).</li>
    130 
    131       <li>If you made changes to the array that you want to commit, and you want
    132       to keep the copy of the array, use <code>JNI_COMMIT</code> (which updates
    133       the underlying array object and retains the copy).</li>
    134 
    135     </ul>
    136 
    137   </li>
    138 
    139   <li>When you call <code>Release...ArrayElements()</code>, return the same
    140   pointer that was originally returned by <code>Get...ArrayElements()</code>. For
    141   example, it's not safe to increment the original pointer (to scan through the
    142   returned array elements) then pass the incremented pointer to
    143   <code>Release...ArrayElements()</code>. Passing this modified pointer can cause
    144   the wrong memory to be freed, resulting in memory corruption.</li>
    145 
    146 </ul>
    147 
    148 <h3 id="Error_Handling">Error handling</h3>
    149 
    150 <p>ART's JNI throws errors in a number of cases where Dalvik didnt. (Once
    151 again, you can catch many such cases by testing with CheckJNI.)</p>
    152 
    153 <p>For example, if <code>RegisterNatives</code> is called with a method that
    154 does not exist (perhaps because the method was removed by a tool such as
    155 <strong>ProGuard</strong>), ART now properly throws {@link
    156 java.lang.NoSuchMethodError}:</p>
    157 
    158 <pre class="no-pretty-print">
    159 08-12 17:09:41.082 13823 13823 E AndroidRuntime: FATAL EXCEPTION: main
    160 08-12 17:09:41.082 13823 13823 E AndroidRuntime: java.lang.NoSuchMethodError:
    161     no static or non-static method
    162     "Lcom/foo/Bar;.native_frob(Ljava/lang/String;)I"
    163 08-12 17:09:41.082 13823 13823 E AndroidRuntime:
    164     at java.lang.Runtime.nativeLoad(Native Method)
    165 08-12 17:09:41.082 13823 13823 E AndroidRuntime:
    166     at java.lang.Runtime.doLoad(Runtime.java:421)
    167 08-12 17:09:41.082 13823 13823 E AndroidRuntime:
    168     at java.lang.Runtime.loadLibrary(Runtime.java:362)
    169 08-12 17:09:41.082 13823 13823 E AndroidRuntime:
    170     at java.lang.System.loadLibrary(System.java:526)
    171 </pre>
    172 
    173 <p>ART also logs an error (visible in logcat) if <code>RegisterNatives</code> is
    174 called with no methods:</p>
    175 
    176 <pre class="no-pretty-print">
    177 W/art     ( 1234): JNI RegisterNativeMethods: attempt to register 0 native
    178 methods for &lt;classname>
    179 </pre>
    180 
    181 <p>In addition, the JNI functions <code>GetFieldID()</code> and
    182 <code>GetStaticFieldID()</code> now properly throw {@link java.lang.NoSuchFieldError}
    183 instead of simply returning null. Similarly, <code>GetMethodID()</code> and
    184 <code>GetStaticMethodID()</code> now properly throw {@link java.lang.NoSuchMethodError}.
    185 This can lead to CheckJNI failures because of the unhandled exceptions or the
    186 exceptions being thrown to Java callers of native code. This makes it
    187 particularly important to test ART-compatible apps with CheckJNI mode.</p>
    188 
    189 <p>ART expects users of the JNI <code>CallNonvirtual...Method()</code> methods
    190 (such as <code>CallNonvirtualVoidMethod()</code>) to use the method's declaring
    191 class, not a subclass, as required by the JNI specification.</p>
    192 
    193 <h2 id="Stack_Size">Preventing Stack Size Issues</h2>
    194 
    195 <p>Dalvik had separate stacks for native and Java code, with a default Java
    196 stack size of 32KB and a default native stack size of 1MB. ART has a unified
    197 stack for better locality. Ordinarily, the ART {@link java.lang.Thread} stack
    198 size should be approximately the same as for Dalvik. However, if you explicitly
    199 set stack sizes, you may need to revisit those values for apps running in
    200 ART.</p>
    201 
    202 <ul>
    203 
    204   <li>In Java, review calls to the {@link
    205   java.lang.Thread#Thread(java.lang.ThreadGroup, java.lang.Runnable,
    206   java.lang.String, long) Thread} constructor that specify an explicit stack
    207   size. For example, you will need to increase the size if {@link
    208   java.lang.StackOverflowError} occurs.</li>
    209 
    210   <li>In C/C++, review use of <code>pthread_attr_setstack()</code> and
    211   <code>pthread_attr_setstacksize()</code> for threads that also run Java code via
    212   JNI. Here is an example of the error logged when an app attempts to call JNI
    213   <code>AttachCurrentThread()</code> when the pthread size is too small:
    214 
    215 <pre class="no-pretty-print">F/art: art/runtime/thread.cc:435]
    216     Attempt to attach a thread with a too-small stack (16384 bytes)</pre>
    217   </li>
    218 
    219 </ul>
    220 
    221 <h2 id="Object_Model_Changes">Object model changes</h2>
    222 
    223 <p>Dalvik incorrectly allowed subclasses to override package-private methods.
    224 ART issues a warning in such cases:</p>
    225 
    226 <pre class="no-pretty-print">
    227 Before Android 4.1, method void com.foo.Bar.quux()
    228 would have incorrectly overridden the package-private method in
    229 com.quux.Quux
    230 </pre>
    231 
    232 <p>If you intend to override a class's method in a different package, declare the
    233 method as <code>public</code> or <code>protected</code>.</p>
    234 
    235 <p>{@link java.lang.Object} now has private fields. Apps that reflect on fields
    236 in their class hierarchies should be careful not to attempt to look at the
    237 fields of {@link java.lang.Object}. For example, if you are iterating up a class
    238 hierarchy as part of a serialization framework, stop when
    239 
    240 <pre>Class.getSuperclass() == java.lang.Object.class</pre>
    241 
    242 instead of continuing until the method returns <code>null</code>.</p>
    243 
    244 <p>Proxy {@link
    245 java.lang.reflect.InvocationHandler#invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[])
    246 InvocationHandler.invoke()} now receives <code>null</code> if there are no
    247 arguments instead of an empty array. This behavior was documented previously but
    248 not correctly handled in Dalvik. Previous versions of <a
    249 href="https://code.google.com/p/mockito/">Mockito</a> have difficulties with
    250 this, so use an updated Mockito version when testing with ART.</p>
    251 
    252 <h2 id="AOT_Fails">Fixing AOT Compilation Issues</h2>
    253 
    254 <p>ART's Ahead-Of-Time (AOT) Java compilation should work for all standard Java
    255 code. Compilation is performed by ART's
    256 <code>dex2oat</code> tool; if you encounter any issues related to
    257 <code>dex2oat</code> at install time, let us know (see <a
    258 href="#Reporting_Problems">Reporting Problems</a>) so we can fix them as quickly
    259 as possible. A couple of issues to note:</p>
    260 
    261 <ul>
    262 
    263   <li>ART does tighter bytecode verification at install time than Dalvik does.
    264   Code produced by the Android build tools should be fine. However, some
    265   post-processing tools (especially tools that perform obfuscation) may produce
    266   invalid files that are tolerated by Dalvik but rejected by ART. We have been
    267   working with tool vendors to find and fix such issues. In many cases, getting
    268   the latest versions of your tools and regenerating the DEX files can fix these
    269   problems.</li>
    270 
    271   <li>Some typical problems that are flagged by the ART verifier include:
    272     <ul>
    273       <li>invalid control flow</li>
    274       <li>unbalanced <code>moniterenter</code>/<code>moniterexit</code></li>
    275       <li>0-length parameter type list size</li>
    276     </ul>
    277   </li>
    278 
    279   <li>Some apps have dependencies on the installed <code>.odex</code> file
    280   format in <code>/system/framework</code>, <code>/data/dalvik-cache</code>, or
    281   in {@link dalvik.system.DexClassLoader}s optimized output directory. These
    282   files are now ELF files and not an extended form of DEX files. While ART tries
    283   to follow the same naming and locking rules as Dalvik, apps should not depend
    284   on the file format; the format is subject to change without notice.</li>
    285 
    286 
    287 
    288 <h2 id="Reporting_Problems">Reporting Problems</h2>
    289 
    290 <p>If you run into any issues that arent due to app JNI issues, report
    291 them via the Android Open Source Project Issue Tracker at <a
    292 href="https://code.google.com/p/android/issues/list">https://code.google.com/p/android/issues/list</a>.
    293 Include an <code>"adb bugreport"</code> and a link to the app in the Google
    294 Play store if available. Otherwise, if possible, attach an APK that reproduces
    295 the issue. Note that issues (including attachments) are publicly
    296 visible.</p>
    297