• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Manage Your App's Memory
2page.tags=ram,low memory,OutOfMemoryError,onTrimMemory
3
4@jd:body
5
6<div id="qv-wrapper">
7<div id="qv">
8
9<h2>In this document</h2>
10<ol>
11  <li><a href="#monitor">Monitor Available Memory and Memory Usage</a>
12    <ul>
13      <li><a href="#AnalyzeRam">Tools for analyzing RAM usage</a></li>
14      <li><a href="#release">Release memory in response to events</a></li>
15      <li><a href="#CheckHowMuchMemory">Check how much memory you should use</a></li>
16    </ul>
17  </li>
18  <li><a href="#code">Use More Efficient Code Constructs</a>
19    <ul>
20      <li><a href="#Services">Use services sparingly</a></li>
21      <li><a href="#DataContainers">Use optimized data containers</a></li>
22      <li><a href="#Abstractions">Be careful with code abstractions</a></li>
23      <li><a href="#NanoProto">Use nano protobufs for serialized data</a></li>
24      <li><a href="#churn">Avoid memory churn</a></li>
25    </ul>
26  </li>
27  <li><a href="#remove">Remove Memory-Intensive Resources and Libraries</a>
28    <ul>
29      <li><a href="#reduce">Reduce overall APK size</a></li>
30      <li><a href="#DependencyInjection">Avoid dependency injection frameworks</a></li>
31      <li><a href="#ExternalLibs">Be careful about using external libraries</a></li>
32    </ul>
33  </li>
34</ol>
35<h2>See Also</h2>
36<ul>
37  <li><a href="{@docRoot}training/articles/memory-overview.html">Overview of Android Memory Management</a>
38  </li>
39  <li><a href="{@docRoot}studio/profile/investigate-ram.html">Investigating Your RAM Usage</a>
40  </li>
41  <li><a href="{@docRoot}topic/performance/reduce-apk-size.html">Reduce APK Size</a></li>
42</ul>
43
44</div>
45</div>
46
47<!-- INTRO #################################################### -->
48
49<p>
50  Random-access memory (RAM) is a valuable
51  resource in any software development environment, but
52  it's even more valuable on a mobile operating system
53  where physical memory is often constrained.
54  Although both the Android Runtime (ART) and Dalvik virtual machine perform
55  routine garbage collection, this does not mean you can ignore
56  when and where your app allocates and releases memory.
57  You still need to avoid
58  introducing memory leaks, usually caused by holding onto
59  object references in static member variables, and
60  release any {@link java.lang.ref.Reference} objects at the appropriate
61  time as defined by
62  lifecycle callbacks.
63</p>
64
65<p>
66  This page explains how you can
67  proactively reduce memory usage within your app.
68  For more information about general
69  practices to clean up your resources when programming in Java,
70  refer to other books or online
71  documentation about managing resource references.
72  If you’re looking for information about how to
73  analyze memory in a running app, read
74  <a href="#AnalyzeRam">Tools for analyzing RAM usage</a>.
75  For more detailed information about how the Android Runtime and Dalvik
76  virtual machine manage memory, see the
77  <a href="{@docRoot}training/articles/memory-overview.html">Overview of Android Memory Management</a>.
78</p>
79
80<!-- Section 1 #################################################### -->
81
82<h2 id="monitor">Monitor Available Memory and Memory Usage</h2>
83
84<p>
85  The Android framework, Android Studio, and Android SDK
86  can help you analyze and adjust your app's memory usage.
87  The Android framework
88  exposes several APIs that allow your app to reduce its memory usage
89  dynamically during runtime. Android Studio and the Android SDK
90  contain several tools  that allow you to investigate how your
91  app uses memory.
92</p>
93
94<!-- Section 1.1 #################################################### -->
95
96<h3 id="AnalyzeRam">Tools for analyzing RAM usage</h3>
97
98<p>
99  Before you can fix the memory usage problems in your app, you first need
100  to find them. Android Studio and the Android SDK include several tools
101  for analyzing memory usage in your app:
102</p>
103
104<ol>
105  <li>
106    The Device Monitor has a Dalvik Debug Monitor Server (DDMS) tool that allows
107    you to inspect memory allocation within your app process.
108    You can use this information to understand how your
109    app uses memory overall. For example, you can force a garbage collection
110    event and then view the types of objects that remain in memory. You can
111    use this information to identify operations or actions within your app
112    that allocate or leave excessive amounts of objects in memory.
113
114    <p>For more information about how to use the DDMS tool, see
115      <a href="/studio/profile/ddms.html">Using DDMS</a>.
116    </p>
117  </li>
118
119  <li>
120    The Memory Monitor in Android Studio shows you how your app allocates
121    memory over the course of a single session.
122    The tool shows a graph of available
123    and allocated Java memory over time, including garbage collection events.
124    You can also initiate garbage collection events and take a snapshot of
125    the Java heap while your app runs. The output from the Memory Monitor tool
126    can help you identify points when your app experiences excessive garbage
127    collection events, leading to app slowness.
128    <p>
129      For more information about how to use Memory Monitor tool, see
130      <a href="{@docRoot}tools/debugging/debugging-memory.html#ViewHeap">Viewing Heap Updates</a>.
131    </p>
132  </li>
133
134  <li>
135    Garbage collection events also show up in the Traceview viewer. Traceview
136    allows you to view trace log files as both a timeline and as a profile
137    of what happened within a method. You can use this tool to determine
138    what code was executing when a garbage collection event occurred.
139    <p>
140      For more information about how to use the Traceview viewer, see
141      <a href="https://developer.android.com/studio/profile/traceview.html">Profiling with Traceview and dmtracedump</a>.
142    </p>
143  </li>
144
145  <li>
146    The Allocation Tracker tool in Android Studio gives you a detailed look
147    at how your app allocates memory.
148    The Allocation Tracker records an app's memory allocations and lists
149    all allocated objects within the profiling snapshot. You can use this
150    tool to track down parts of your code that allocate too many objects.
151
152    <p>
153      For more information about how to use the Allocation Tracker tool, see
154      <a href="{docRoot}studio/profile/allocation-tracker-walkthru.html">Allocation Tracker Walkthrough</a>.
155    </p>
156  </li>
157
158</ol>
159
160<!-- Section 1.2 #################################################### -->
161
162<h3 id="release">Release memory in response to events</h3>
163
164<p>
165  An Android device can run with varying amounts of free memory
166  depending on the physical amount of RAM on the device and how the user
167  operates it. The system broadcasts signals to indicate when it is under
168  memory pressure, and apps should listen for these signals and adjust
169  their memory usage as appropriate.
170</p>
171
172</p>
173  You can use the {@link android.content.ComponentCallbacks2} API
174  to listen for these signals and then adjust your memory
175  usage in response to app lifecycle
176  or device events. The
177  {@link android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()}
178  method allows your app to listen for memory related events when the app runs
179  in the foreground (is visible) and when it runs in the background.
180</p>
181
182<p>
183  To listen for these events, implement the {@link
184  android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()}
185  callback in your {@link android.app.Activity}
186  classes, as shown in the following code snippet.
187</p>
188
189<pre class="prettyprint">
190import android.content.ComponentCallbacks2;
191// Other import statements ...
192
193public class MainActivity extends AppCompatActivity
194    implements ComponentCallbacks2 {
195
196    // Other activity code ...
197
198    /**
199     * Release memory when the UI becomes hidden or when system resources become low.
200     * @param level the memory-related event that was raised.
201     */
202    public void onTrimMemory(int level) {
203
204        // Determine which lifecycle or system event was raised.
205        switch (level) {
206
207            case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
208
209                /*
210                   Release any UI objects that currently hold memory.
211
212                   The user interface has moved to the background.
213                */
214
215                break;
216
217            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
218            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
219            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
220
221                /*
222                   Release any memory that your app doesn't need to run.
223
224                   The device is running low on memory while the app is running.
225                   The event raised indicates the severity of the memory-related event.
226                   If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will
227                   begin killing background processes.
228                */
229
230                break;
231
232            case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
233            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
234            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
235
236                /*
237                   Release as much memory as the process can.
238
239                   The app is on the LRU list and the system is running low on memory.
240                   The event raised indicates where the app sits within the LRU list.
241                   If the event is TRIM_MEMORY_COMPLETE, the process will be one of
242                   the first to be terminated.
243                */
244
245                break;
246
247            default:
248                /*
249                  Release any non-critical data structures.
250
251                  The app received an unrecognized memory level value
252                  from the system. Treat this as a generic low-memory message.
253                */
254                break;
255        }
256    }
257}
258</pre>
259
260<p>
261  The
262  {@link android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()}
263  callback was added in Android 4.0 (API level 14). For earlier versions,
264  you can use the
265  {@link android.content.ComponentCallbacks#onLowMemory()}
266  callback as a fallback for older versions, which is roughly equivalent to the
267  {@link android.content.ComponentCallbacks2#TRIM_MEMORY_COMPLETE} event.
268</p>
269
270<!-- Section 1.3 #################################################### -->
271
272<h3 id="CheckHowMuchMemory">Check how much memory you should use</h3>
273
274<p>
275  To allow multiple running processes, Android sets a hard limit
276  on the heap size alloted for each app. The exact heap size limit varies
277  between devices based on how much RAM the device
278  has available overall. If your app has reached the heap capacity and
279  tries to allocate more
280  memory, the system throws an {@link java.lang.OutOfMemoryError}.
281</p>
282
283<p>
284  To avoid running out of memory, you can to query the system to determine
285  how much heap space you have available on the current device.
286  You can query the system for this figure by calling
287  {@link android.app.ActivityManager#getMemoryInfo(android.app.ActivityManager.MemoryInfo) getMemoryInfo()}.
288  This returns an
289  {@link android.app.ActivityManager.MemoryInfo } object that provides
290  information about the device's
291  current memory status, including available memory, total memory, and
292  the memory threshold&mdash;the memory level below which the system begins
293  to kill processes. The
294  {@link android.app.ActivityManager.MemoryInfo } class also exposes a simple
295  boolean field,
296  {@link android.app.ActivityManager.MemoryInfo#lowMemory }
297  that tells you whether the device is running low on memory.
298</p>
299
300<p>
301  The following code snippet shows an example of how you can use the
302  {@link android.app.ActivityManager#getMemoryInfo(android.app.ActivityManager.MemoryInfo) getMemoryInfo()}.
303  method in your application.
304</p>
305
306<pre class="prettyprint">
307public void doSomethingMemoryIntensive() {
308
309    // Before doing something that requires a lot of memory,
310    // check to see whether the device is in a low memory state.
311    ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();
312
313    if (!memoryInfo.lowMemory) {
314        // Do memory intensive work ...
315    }
316}
317
318// Get a MemoryInfo object for the device's current memory status.
319private ActivityManager.MemoryInfo getAvailableMemory() {
320    ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
321    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
322    activityManager.getMemoryInfo(memoryInfo);
323    return memoryInfo;
324}
325</pre>
326
327<!-- Section 2 #################################################### -->
328
329<h2 id="code">Use More Memory-Efficient Code Constructs</h2>
330
331<p>
332  Some Android features, Java classes, and code constructs tend to
333  use more memory than others. You can minimize how
334  much memory your app uses by choosing more efficient alternatives in
335  your code.
336</p>
337
338<!-- Section 2.1 #################################################### -->
339
340<h3 id="Services">Use services sparingly</h3>
341
342<p>
343  Leaving a service running when it’s not needed is
344  <strong>one of the worst memory-management
345  mistakes</strong> an Android app can make. If your app needs a
346  <a href="{@docRoot}guide/components/services.html">service</a>
347  to perform work in the background, do not keep it running unless
348  it needs to run a job. Remember to stop your service when it has completed
349  its task. Otherwise, you can inadvertently cause a memory leak.
350</p>
351
352<p>
353  When you start a service, the system prefers to always keep the process
354  for that service running. This behavior
355  makes services processes very expensive
356  because the RAM used by a service remains unavailable to other processes.
357  This reduces the number of cached processes that the system can keep in
358  the LRU cache, making app switching less efficient. It can even lead to
359  thrashing in the system when memory is tight and the system can’t
360  maintain enough processes to host all the services currently running.
361</p>
362
363<p>
364  You should generally avoid use of persistent services because of
365  the on-going demands they place on available memory. Instead, we
366  recommend that you use an alternative implementation
367  such as {@link android.app.job.JobScheduler}. For more information about
368  how to use {@link android.app.job.JobScheduler} to schedule background
369  processes, see
370  <a href="/topic/performance/background-optimization.html">Background Optimizations</a>.
371<p>
372  If you must use a service, the
373  best way to limit the lifespan of your service is to use an {@link
374  android.app.IntentService}, which finishes
375  itself as soon as it's done handling the intent that started it.
376  For more information, read
377  <a href="{@docRoot}training/run-background-service/index.html">Running in a Background Service</a>.
378</p>
379
380<!-- Section 2.2 #################################################### -->
381
382<h3 id="DataContainers">Use optimized data containers</h3>
383
384<p>
385  Some of the classes provided by the programming language are not optimized for
386  use on mobile devices. For example, the generic
387  {@link java.util.HashMap} implementation can be quite memory
388  inefficient because it needs a separate entry object for every mapping.
389</p>
390
391<p>
392  The Android framework includes several optimized data containers, including
393  {@link android.util.SparseArray}, {@link android.util.SparseBooleanArray},
394  and {@link android.support.v4.util.LongSparseArray}.
395  For example, the {@link android.util.SparseArray} classes are more
396  efficient because they avoid the system's need to
397  <acronym title="Automatic conversion from primitive types to object classes (such as int to Integer)">autobox</acronym>
398  the key and sometimes value (which creates yet another object or
399  two per entry).
400</p>
401
402<p>
403  If necessary, you can always switch to raw arrays for a really lean data
404  structure.
405</p>
406
407<!-- Section 2.3 #################################################### -->
408
409<h3 id="Abstractions">Be careful with code abstractions</h3>
410
411<p>
412  Developers often use abstractions simply as a good programming practice,
413  because abstractions can improve code flexibility and maintenance.
414  However, abstractions come at a significant cost:
415  generally they require a fair amount more code that
416  needs to be executed, requiring more time and
417  more RAM for that code to be mapped into memory.
418  So if your abstractions aren't supplying a
419  significant benefit, you should avoid them.
420</p>
421
422<p>
423  For example, enums often require more than twice as much memory as static
424  constants. You should strictly avoid using enums on Android.
425</p>
426
427<!-- Section 2.4 #################################################### -->
428
429<h3 id="NanoProto">Use nano protobufs for serialized data</h3>
430
431<p>
432  <a href="https://developers.google.com/protocol-buffers/docs/overview">Protocol buffers</a>
433  are a language-neutral, platform-neutral, extensible mechanism
434  designed by Google for serializing structured data&mdash;similar to XML, but
435  smaller, faster, and simpler. If you decide to use
436  protobufs for your data, you should always use nano protobufs in your
437  client-side code. Regular protobufs generate extremely verbose code, which
438  can cause many kinds of problems in your app such as
439  increased RAM use, significant APK size increase, and slower execution.
440</p>
441
442<p>
443  For more information, see the "Nano version" section in the
444  <a href="https://android.googlesource.com/platform/external/protobuf/+/master/java/README.txt"
445class="external-link">protobuf readme</a>.
446</p>
447
448<!-- Section 2.5 #################################################### -->
449
450<h3 id="churn">Avoid memory churn</h3>
451
452<p>
453  As mentioned previously, garbage collections events don't normally affect
454  your app's performance. However, many garbage collection events that occur
455  over a short period of time can quickly eat up your frame time. The more time
456  that the system spends on garbage collection, the less time it has to do
457  other stuff like rendering or streaming audio.
458</p>
459
460<p>
461  Often, <em>memory churn</em> can cause a large number of
462  garbage collection events to occur. In practice, memory churn describes the
463  number of allocated temporary objects that occur in a given amount of time.
464</p>
465
466<p>
467  For example, you might allocate multiple temporary objects within a
468  <code>for</code> loop. Or you might create new
469  {@link android.graphics.Paint} or {@link android.graphics.Bitmap}
470  objects inside the
471  {@link android.view.View#onDraw(android.graphics.Canvas) onDraw()}
472  function of a view.
473  In both cases, the app creates a lot of objects quickly at high volume.
474  These can quickly consume all the available memory in the young generation,
475  forcing a garbage collection event to occur.
476</p>
477
478<p>
479  Of course, you need to find the places in your code where
480  the memory churn is high before you can fix them. Use the tools discussed in
481  <a href="#AnalyzeRam">Analyze your RAM usage</a>
482</p>
483
484<p>
485  Once you identify the problem areas in your code, try to reduce the number of
486  allocations within performance critical areas. Consider moving things out of
487  inner loops or perhaps moving them into a
488  <a href="https://en.wikipedia.org/wiki/Factory_method_pattern" class="external-link">Factory</a>
489  based allocation structure.
490</p>
491
492<!-- Section 3 #################################################### -->
493
494<h2 id="remove">Remove Memory-Intensive Resources and Libraries</h2>
495
496<p>
497  Some resources and libraries within your code can gobble up memory without
498  you knowing it. Overall size of your APK, including third-party libraries
499  or embedded resources, can affect how much memory your app consumes. You can
500  improve your app's memory consumption by removing any redundant, unnecessary,
501  or bloated components, resources, or libraries from your code.
502</p>
503
504<!-- Section 3.1 #################################################### -->
505
506<h3 id="reduce">Reduce overall APK size</h3>
507
508<p>
509  You can significantly reduce your app's memory usage by reducing the overall
510  size of your app. Bitmap size, resources, animation frames, and third-party
511  libraries can all contribute to the size of your APK.
512  Android Studio and the Android SDK provide multiple tools
513  to help you reduce the size of your resources and external dependencies.
514</p>
515
516<p>
517  For more information about how to reduce your overall APK size, see
518  <a href="{@docRoot}topic/performance/reduce-apk-size.html">Reduce APK Size</a>.
519</p>
520
521<!-- Section 3.2 #################################################### -->
522
523<h3 id="DependencyInjection">Use caution with dependency injection frameworks</h3>
524
525<p>
526  Dependency injection framework such as
527  <a href="https://code.google.com/p/google-guice/" class="external-link">Guice</a>
528  or
529  <a href="https://github.com/roboguice/roboguice" class="external-link">RoboGuice</a>
530  can simplify the code you write and provide an adaptive environment
531  that's useful for testing and other configuration changes. However, dependency
532  frameworks aren't always optimized for mobile devices.
533</p>
534
535<p>
536  For example, these frameworks tend to initialize processes by
537  scanning your code for annotations. This which can require significant
538  amounts of your code to be mapped into RAM unnecessarily. The system
539  allocates these mapped pages into clean memory so Android can drop them; yet
540  that can't happen until the pages have remained in memory for a long period
541  of time.
542 </p>
543
544<p>
545  If you need to use a dependency injection framework in your app, consider
546  using
547  <a class="external-link" href="http://google.github.io/dagger/">Dagger</a>
548  instead. For example, Dagger does not use reflection to scan your app's code.
549  Dagger's strict implementation means that it can be used in Android apps
550  without needlessly increasing memory usage.
551</p>
552
553<!-- Section 3.3 #################################################### -->
554
555<h3 id="ExternalLibs">Be careful about using external libraries</h3>
556
557<p>
558  External library code is often not written for mobile environments and
559  can be inefficient when used
560  for work on a mobile client. When you decide to use an
561  external library, you may need to optimize that library for mobile devices.
562  Plan for that work up-front and analyze the library in terms of code size and
563  RAM footprint before deciding to use it at all.
564</p>
565
566<p>
567  Even some mobile-optimized libraries can cause problems due to differing
568  implementations. For example, one library may use nano protobufs
569  while another uses micro protobufs, resulting in two different protobuf
570  implementations in your app. This can happen with different
571  implementations of logging, analytics, image loading frameworks,
572  caching, and many other things you don't expect.
573</p>
574
575<p>
576  Although <a href="{@docRoot}tools/help/proguard.html">ProGuard</a> can
577  help to remove APIs and resources with the right flags, it can't remove a
578  library's large internal dependencies. The features that you want in these
579  libraries may require lower-level dependencies. This becomes especially
580  problematic when you use an {@link android.app.Activity } subclass from a
581  library (which will tend to have wide swaths of dependencies),
582  when libraries use reflection (which is common and means you need to spend a
583  lot of time manually tweaking ProGuard to get it to work), and so on.
584</p>
585
586<p>
587  Also avoid using a shared library for just one or two features out of dozens.
588  You don't want to pull in a large amount of code and overhead that
589  you don't even use. When you consider whether to use a library, look for
590  an implementation that strongly matches what you need. Otherwise, you might
591  decide to create your own implementation.
592</p>
593
594