• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &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}
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