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>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
35href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html">Debugging
36Android 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
43performance and smoothness of the Android platform and apps. (You can find more
44information about ART's new features in <a
45href="http://source.android.com/devices/tech/dalvik/art.html">Introducing
46ART</a>.)</p>
47
48<p>Currently, ART is available on a number of Android 4.4 devices, such as the
49Nexus 4, Nexus 5, Nexus 7, and Google Play edition devices.
50At this time, all devices still use Dalvik as the default runtime. We encourage
51you to test your apps for ART compatibility and to take advantage of ART's new
52features. However, for the time being, you should also take care to maintain
53compatibility with Dalvik.</p>
54
55<p>This document lets you know about things to watch for when migrating an
56existing app to be compatible with ART. Most apps should just work when
57running with ART. However, some techniques that work on Dalvik do not work on
58ART. 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
63java.lang.System#gc() System.gc()} to prompt garbage collection (GC). This should be
64far less necessary with ART, particularly if you're invoking garbage collection
65to prevent <a
66href="{@docRoot}/tools/debugging/debugging-memory.html#LogMessages"><code>GC_FOR_ALLOC</code></a>-type
67occurrences or to reduce fragmentation. You can verify which runtime is in use
68by calling {@link java.lang.System#getProperty(java.lang.String)
69System.getProperty("java.vm.version")}. If ART is in use, the property's value
70is <code>"2.0.0"</code> or higher.</p>
71
72<p>Furthermore, a compacting garbage collector is under development in the <a
73href="https://source.android.com">Android Open-Source Project (AOSP)</a> to
74improve memory management. Because of this, you should avoid using techniques
75that are incompatible with compacting GC (such as saving pointers to object
76instance data). This is particularly important for apps that make use of the
77Java Native Interface (JNI). For more information, see <a
78href="#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
83to use CheckJNI mode to catch common problems. If your app makes use of C/C++
84code, you should review the following article:</p>
85
86<p><a
87href="http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html">Debugging
88Android 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
93Android Open Source Project (AOSP). Once the compacting garbage collector is in
94use, objects may be moved in memory. If you use C/C++ code, do not
95perform operations that are incompatible with compacting GC. We have enhanced
96CheckJNI to identify some potential issues (as described in <a
97href="http://android-developers.blogspot.com/2011/11/jni-local-reference-changes-in-ics.html">JNI
98Local 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>
102functions. In runtimes with non-compacting GC, the
103<code>Get...ArrayElements()</code> functions typically return a reference to the
104actual memory backing the array object. If you make a change to one of the
105returned array elements, the array object is itself changed (and the arguments
106to <code>Release...ArrayElements()</code> are usually ignored). However, if
107compacting GC is in use, the <code>Get...ArrayElements()</code> functions may
108return a copy of the memory. If you misuse the reference when compacting GC is
109in 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
151again, 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
154does not exist (perhaps because the method was removed by a tool such as
155<strong>ProGuard</strong>), ART now properly throws {@link
156java.lang.NoSuchMethodError}:</p>
157
158<pre class="no-pretty-print">
15908-12 17:09:41.082 13823 13823 E AndroidRuntime: FATAL EXCEPTION: main
16008-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"
16308-12 17:09:41.082 13823 13823 E AndroidRuntime:
164    at java.lang.Runtime.nativeLoad(Native Method)
16508-12 17:09:41.082 13823 13823 E AndroidRuntime:
166    at java.lang.Runtime.doLoad(Runtime.java:421)
16708-12 17:09:41.082 13823 13823 E AndroidRuntime:
168    at java.lang.Runtime.loadLibrary(Runtime.java:362)
16908-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
174called with no methods:</p>
175
176<pre class="no-pretty-print">
177W/art     ( 1234): JNI RegisterNativeMethods: attempt to register 0 native
178methods 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}
183instead of simply returning null. Similarly, <code>GetMethodID()</code> and
184<code>GetStaticMethodID()</code> now properly throw {@link java.lang.NoSuchMethodError}.
185This can lead to CheckJNI failures because of the unhandled exceptions or the
186exceptions being thrown to Java callers of native code. This makes it
187particularly 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
191class, 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
196stack size of 32KB and a default native stack size of 1MB. ART has a unified
197stack for better locality. Ordinarily, the ART {@link java.lang.Thread} stack
198size should be approximately the same as for Dalvik. However, if you explicitly
199set stack sizes, you may need to revisit those values for apps running in
200ART.</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.
224ART issues a warning in such cases:</p>
225
226<pre class="no-pretty-print">
227Before Android 4.1, method void com.foo.Bar.quux()
228would have incorrectly overridden the package-private method in
229com.quux.Quux
230</pre>
231
232<p>If you intend to override a class's method in a different package, declare the
233method 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
236in their class hierarchies should be careful not to attempt to look at the
237fields of {@link java.lang.Object}. For example, if you are iterating up a class
238hierarchy as part of a serialization framework, stop when
239
240<pre>Class.getSuperclass() == java.lang.Object.class</pre>
241
242instead of continuing until the method returns <code>null</code>.</p>
243
244<p>Proxy {@link
245java.lang.reflect.InvocationHandler#invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[])
246InvocationHandler.invoke()} now receives <code>null</code> if there are no
247arguments instead of an empty array. This behavior was documented previously but
248not correctly handled in Dalvik. Previous versions of <a
249href="https://code.google.com/p/mockito/">Mockito</a> have difficulties with
250this, 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
255code. 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
258href="#Reporting_Problems">Reporting Problems</a>) so we can fix them as quickly
259as 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
291them via the Android Open Source Project Issue Tracker at <a
292href="https://code.google.com/p/android/issues/list">https://code.google.com/p/android/issues/list</a>.
293Include an <code>"adb bugreport"</code> and a link to the app in the Google
294Play store if available. Otherwise, if possible, attach an APK that reproduces
295the issue. Note that issues (including attachments) are publicly
296visible.</p>
297