2

While profiling my app, I found, that retrieving the NsdManager by using

nsdManager = (NsdManager) getSystemService(Context.NSD_SERVICE);  // LEAKS!

is leaking the Activity, while

nsdManager = (NsdManager) getApplicationContext().getSystemService(Context.NSD_SERVICE);

does not. I made a small test app, that does nothing else with the NsdManager than retrieving it using the Activity context, but it's still leaking the activity. Is this a bug? Do I really have to use the application context all the time?

Device: Emulator (Android 11, API 30, x86)

roplacebo
  • 2,837
  • 2
  • 17
  • 19
  • How are you determining that it is being leaked? What is leaking it? Are you seeing the leak on older versions of Android? – CommonsWare Nov 18 '20 at 20:20
  • GitHub: https://github.com/roplacebo/NsdManager.git. Click Button to go to the NsdActivity, where NsdManager is retrieved from the Activity Context. Then go back.Heap Dumps with Leak Canary and Memory Profiler. Same with Samsung Galaxy Tab S2 (Nougat) – roplacebo Nov 18 '20 at 21:11
  • 1
    OK, I can reproduce the problem with your project. I am uncertain how "real" the leak is. Something deep in Android's guts is holding the `AsyncChannel` that has a reference to your activity, and I do not know if/when that reference will be released. You might consider [following this FAQ entry's instructions](https://square.github.io/leakcanary/faq/#can-a-leak-be-caused-by-the-android-sdk) to try to determine if this is what LeakCanary refers to as "a Library leak" or not. – CommonsWare Nov 19 '20 at 00:19
  • Thanks for looking into it! I filed a bug here: https://issuetracker.google.com/issues/173689855 – roplacebo Nov 19 '20 at 12:37

1 Answers1

0

This problem seems similar to memory leak issues with obtaining WIFI_SERVICE.

When doing:

activity.getSystemService(Context.WIFI_SERVICE);

Android Studio lint shows the following warning.

The WIFI_SERVICE must be looked up on the 
Application context or memory will leak on
devices < Android N. Try changing activity
to activity.getApplicationContext().

Although there is no lint warning with NSD_SERVICE and because I see memory leaks referencing NsdManager when using:

activity.getSystemService(Context.NSD_SERVICE);

I think using:

activity.getApplicationContext().getSystemService(Context.NSD_SERVICE);

seems like the correct action.

Java42
  • 587
  • 5
  • 13