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 <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