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