| Andrew Solovay | 220cf29 | 2014-05-20 15:50:13 -0700 | [diff] [blame] | 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) |
| Andrew Solovay | dccf940 | 2014-06-24 13:04:54 -0700 | [diff] [blame] | 69 | System.getProperty("java.vm.version")}. If ART is in use, the property's value |
| Andrew Solovay | 220cf29 | 2014-05-20 15:50:13 -0700 | [diff] [blame] | 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 didn’t. (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 <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 aren’t 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> |