1 page.title=Manage Your App's Memory 2 page.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 youre 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"> 190 import android.content.ComponentCallbacks2; 191 // Other import statements ... 192 193 public 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—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"> 307 public 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. 319 private 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 its 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 cant 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—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" 445 class="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