1page.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 85java.lang.System#gc() System.gc()} to prompt garbage collection (GC). This should be 86far less necessary with ART, particularly if you're invoking garbage collection 87to prevent <a 88href="{@docRoot}tools/debugging/debugging-memory.html#LogMessages"><code>GC_FOR_ALLOC</code></a>-type 89occurrences or to reduce fragmentation. You can verify which runtime is in use 90by calling {@link java.lang.System#getProperty(java.lang.String) 91System.getProperty("java.vm.version")}. If ART is in use, the property's value 92is <code>"2.0.0"</code> or higher.</p> 93 94<p>Furthermore, a compacting garbage collector is under development in the <a 95href="https://source.android.com">Android Open-Source Project (AOSP)</a> to 96improve memory management. Because of this, you should avoid using techniques 97that are incompatible with compacting GC (such as saving pointers to object 98instance data). This is particularly important for apps that make use of the 99Java Native Interface (JNI). For more information, see <a 100href="#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 105to use CheckJNI mode to catch common problems. If your app makes use of C/C++ 106code, you should review the following article:</p> 107 108<p><a 109href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html">Debugging 110Android 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 115Android Open Source Project (AOSP). Once the compacting garbage collector is in 116use, objects may be moved in memory. If you use C/C++ code, do not 117perform operations that are incompatible with compacting GC. We have enhanced 118CheckJNI to identify some potential issues (as described in <a 119href="http://android-developers.blogspot.com/2011/11/jni-local-reference-changes-in-ics.html">JNI 120Local 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> 124functions. In runtimes with non-compacting GC, the 125<code>Get...ArrayElements()</code> functions typically return a reference to the 126actual memory backing the array object. If you make a change to one of the 127returned array elements, the array object is itself changed (and the arguments 128to <code>Release...ArrayElements()</code> are usually ignored). However, if 129compacting GC is in use, the <code>Get...ArrayElements()</code> functions may 130return a copy of the memory. If you misuse the reference when compacting GC is 131in 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 doesn’t. (Once 173again, 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 176does not exist (perhaps because the method was removed by a tool such as 177<strong>ProGuard</strong>), ART now properly throws {@link 178java.lang.NoSuchMethodError}:</p> 179 180<pre class="no-pretty-print"> 18108-12 17:09:41.082 13823 13823 E AndroidRuntime: FATAL EXCEPTION: main 18208-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" 18508-12 17:09:41.082 13823 13823 E AndroidRuntime: 186 at java.lang.Runtime.nativeLoad(Native Method) 18708-12 17:09:41.082 13823 13823 E AndroidRuntime: 188 at java.lang.Runtime.doLoad(Runtime.java:421) 18908-12 17:09:41.082 13823 13823 E AndroidRuntime: 190 at java.lang.Runtime.loadLibrary(Runtime.java:362) 19108-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 196called with no methods:</p> 197 198<pre class="no-pretty-print"> 199W/art ( 1234): JNI RegisterNativeMethods: attempt to register 0 native 200methods for <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} 205instead of simply returning null. Similarly, <code>GetMethodID()</code> and 206<code>GetStaticMethodID()</code> now properly throw {@link java.lang.NoSuchMethodError}. 207This can lead to CheckJNI failures because of the unhandled exceptions or the 208exceptions being thrown to Java callers of native code. This makes it 209particularly 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 213class, 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 218stack size of 32KB and a default native stack size of 1MB. ART has a unified 219stack for better locality. Ordinarily, the ART {@link java.lang.Thread} stack 220size should be approximately the same as for Dalvik. However, if you explicitly 221set stack sizes, you may need to revisit those values for apps running in 222ART.</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. 246ART issues a warning in such cases:</p> 247 248<pre class="no-pretty-print"> 249Before Android 4.1, method void com.foo.Bar.quux() 250would have incorrectly overridden the package-private method in 251com.quux.Quux 252</pre> 253 254<p>If you intend to override a class's method in a different package, declare the 255method 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 258in their class hierarchies should be careful not to attempt to look at the 259fields of {@link java.lang.Object}. For example, if you are iterating up a class 260hierarchy as part of a serialization framework, stop when 261 262<pre>Class.getSuperclass() == java.lang.Object.class</pre> 263 264instead of continuing until the method returns <code>null</code>.</p> 265 266<p>Proxy {@link 267java.lang.reflect.InvocationHandler#invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[]) 268InvocationHandler.invoke()} now receives <code>null</code> if there are no 269arguments instead of an empty array. This behavior was documented previously but 270not correctly handled in Dalvik. Previous versions of <a 271href="https://code.google.com/p/mockito/">Mockito</a> have difficulties with 272this, 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 277code. 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 280href="#Reporting_Problems">Reporting Problems</a>) so we can fix them as quickly 281as 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 aren’t due to app JNI issues, report 313them via the Android Open Source Project Issue Tracker at <a 314href="https://code.google.com/p/android/issues/list">https://code.google.com/p/android/issues/list</a>. 315Include an <code>"adb bugreport"</code> and a link to the app in the Google 316Play store if available. Otherwise, if possible, attach an APK that reproduces 317the issue. Note that issues (including attachments) are publicly 318visible.</p> 319