Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Brief History of Memory Leaks - Kotlin Budape...

A Brief History of Memory Leaks - Kotlin Budapest Meetup May 3rd

Memory and threading in is some of the most difficult and complicated topics in Android. This talk introduces what memory leaks are, and why they’re so hard to find. Taken from excerpts of the newly published O'Reilly book "Programming Android with Kotlin: Achieving Structured Concurrency with Coroutines", this talk take a light-hearted approach at some of the colorful developments Android has gone through the years.

From “Why did AsyncTask get deprecated?” to resource leaks in background threads, we look at memory leaks in Android as we’ve uncovered them through the years. To understand quirks of memory leaks in Android, join us for some historical context, a little empathy, and a kinder view of open-source development.

mvndy_hd

June 16, 2022
Tweet

More Decks by mvndy_hd

Other Decks in Technology

Transcript

  1. Timeline JetBrains: Coroutines are like light-weight threads 2017 Roman Elizarov

    [JB]: Coroutines in Practice 2018 Roman Elizarov [JB]: Structured Concurrency 2019
  2. Timeline JetBrains: Coroutines are light-weight threads Roman Elizarov [JB]: Coroutines

    in Practice 2017 2018 Roman Elizarov: Structured Concurrency JetBrains: Coroutines are light-weight threads 2017 Android Developer Blog: Avoiding memory leaks 2009
  3. Timeline JetBrains: Coroutines are light-weight threads Roman Elizarov [JB]: Coroutines

    in Practice 2016 KT-1622: Coroutine does not clear internal state Fixed Kotlin 1.4 2017 2018 Roman Elizarov: Structured Concurrency JetBrains: Coroutines are light-weight threads 2017 Android Developer Blog: Avoiding memory leaks 2009
  4. Memory leaks are everywhere! They're in your apps. They're in

    your IDEs. They're in your phones. We're going to creating them. And we're going to keep finding them and fixing them.
  5. What is a memory leak? • When the heap holds

    to allocated memory longer than necessary • When an object is allocated in memory but is unreachable for the running program @hinchman_amanda #programmingandroidwithkotlin
  6. What is a memory leak? • When the heap holds

    to allocated memory longer than necessary ◦ Leaking references for scheduled work and concurrency • When an object is allocated in memory but is unreachable for the running program ◦ Passing Android components outside of Main threading • Can be found in your own code or 3rd party libraries or OS @hinchman_amanda #programmingandroidwithkotlin
  7. Why do memory leaks matter? • Application quality depends on

    user experience • Android has very limited resources in hardware capacity ◦ ~15% of Android users use Lollipop and below on their devices¹ • Memory leaks can cause "jank", OOM, and other strange behaviors ¹ Bradshaw, Kyle. “Google Kills Android Distribution Numbers on the Web - 9to5Google.” 9To5Google
  8. Heap + Garbage collection (GC) • Every application has its

    own process and heap ◦ If your app reaches heap capacity and tries to allocate for more memory, it will receive an OOM • GC - frees allocated memory back to heap • GC will: ◦ Find data objects in a program that cannot be reached in the future ◦ Reclaim the resources used by those objects • Objects eligible for GC: ◦ Nullifying the object reference ◦ Re-assigning the object reference ◦ Object created inside method
  9. Explicit Memory Leaks • Be wary of third-party libraries that

    may reference the use of an Android resource • Can be spotted within code review ¹ “Issue 145468285: Memory Leak with Nested Fragments and Data Binding.” Issuetracker.google.com, Google, 2 Dec. 2019, 09:01am PT, issuetracker.google.com/issues/145468285#comment6.
  10. Android Main (UI) Thread • Interacts and manipulates UI widgets

    and views • Allows Android components in the application to interact with the Android OS • All components run within the same process instantiates on the UI thread • Storing references to Android components in background threads can cause leaks @hinchman_amanda #programmingandroidwithkotlin
  11. Explicit leaks Look for references to Android Context/Activity/Fragment/View components accidentally

    stored or injected into: • static objects • background threads • RecyclerViews!!!!! @hinchman_amanda #programmingandroidwithkotlin
  12. Implicit Memory Leaks • Be wary of third-party libraries that

    may reference the use of an Android resource • Harder to see ¹ “Issue 145468285: Memory Leak with Nested Fragments and Data Binding.” Issuetracker.google.com, Google, 2 Dec. 2019, 09:01am PT, issuetracker.google.com/issues/145468285#comment6.
  13. Timeline JetBrains: Coroutines are light-weight threads Roman Elizarov [JB]: Coroutines

    in Practice 2016 KT-1622: Coroutine does not clear internal state Fixed Kotlin 1.4 2017 2018 Roman Elizarov: Structured Concurrency JetBrains: Coroutines are light-weight threads 2017 Android Developer Blog: Avoiding memory leaks 2009
  14. Implicit Memory Leaks: Async Tasks class MainActivity : Activity {

    /*removed for brevity */ inner class SomeAsyncTask: AsyncTask<Void, Void, String> { override fun doInBackground( ) { /*removed for brevity */ } override fun onPostExecute(results: String): String { /* removed for brevity */ } }
  15. Implicit Memory Leaks: Fragment Views • Be wary of third-party

    libraries that may reference the use of an Android resource • The Fragment's View (but not the Fragment itself) is destroyed when a Fragment is put on the backstack² ◦ Developers are expected to clear refs for views in Fragment::onDestroyView ¹ “Issue 145468285: Memory Leak with Nested Fragments and Data Binding.” Issuetracker.google.com, Google, 2 Dec. 2019, 09:01am PT, issuetracker.google.com/issues/145468285#comment6.
  16. Review • When the heap holds to allocated memory longer

    than necessary • Explicit Memory Leaks ◦ Avoid passing Android components outside of Main threading • Implicit Memory Leaks ▪ Leaking references for scheduled work and concurrency
  17. Limitations of Android threading model - Callbacks rapidly becomes complex

    + hard to maintain without thoughtful design - Must account for listening to lifecycle events - Requires a thread-safe way of interrupting threads
  18. onHikesFetched - total distance - length of last hike in

    both time + distance - current weather - favorite hikes
  19. Limitations of Android threading model • Tasks can be broken

    down into threads ◦ CPUs can only execute a certain number of threads in parallel
  20. • What about mem leaks? ◦ we've addressed a lot

    of potential areas already • But we have missed one consideration - cancellation
  21. Cancellation difficulties in Threading • Devs cannot control when a

    thread finishes ◦ A thread finishes when the work is complete ◦ It cannot finish if an injected resource lives a long time • Execution flow hard to control ◦ If one fails, the others are still running
  22. Limitations of the Android threading model (cont...) - in threads,

    exceptions are not propagated - Android designers made the choice to crash the app if there is an unhandled UncaughtExceptionHandler as a choice to make it fail-fast - Good for Android, back for app developers who want to keep customers
  23. • Coroutines does not require data primitives like Handlers to

    pass data • Safe cancellation mechanisms encouraged in coroutines Good news - cancellation mechanism is easier in coroutines
  24. Implementing onHikesFetched with coroutines • Fetching weather could involve multiple

    APIs, depending on the nature of the data • Wind, temperature data fetched separately from different sources
  25. What kind of exception are there? • Exposed exceptions ◦

    The only kinds of exceptions which can be handled by client code try/catch • Unhandled exceptions ◦ typically makes your application crash (or at least, recovering from them might leave the app in an undetermined state
  26. Unhandled Exceptions by registering a custom CoroutineExceptionHandler (CEH) • this

    stops the exception's propagation • avoids a program crash
  27. register CEH to: ◦ launch must be coroutine root builder

    ◦ a scope ◦ a supervisorScope child Unhandled Exceptions by registering a custom CoroutineExceptionHandler (CEH)
  28. Avoiding potential Memory Leaks • Watch how you interact with

    the Android API Framework • Follow the constraints of the Android threading model • Profile your code with AS or LeakCanary • Ask yourself "could I be interacting with a hardware component"? ◦ Databases, networking, Android graphics, location, etc etc
  29. Avoiding potential Memory Leaks • Pay special care to static

    references, since they are stored longest in heap ◦ Never store Android components like Activities, Services, views, etc. • Do not reference Activities/Views/Fragments/Context and other Android components outside the UI thread • Use Glide if you can, but if you have to work with bitmaps, make sure to recycle/nullify • Avoid the use of persistent services whenever possible
  30. Interested in hearing more? • Android threading model • Thread

    safety strategies • Thread cancellation mechanisms • Structured concurrency • Coroutines • Channels • Flows @hinchman_amanda