Similar memory leak for WebView banners and Native ads

404 views
Skip to first unread message

Bubblesoft

unread,
Jun 3, 2024, 6:28:38 AM6/3/24
to Google Mobile Ads SDK Developers
Reported using Leak Canary 3.0-alpha-7.

I have an app with an Activity that can display either a WebView banner or a Native ad ( one or the other, not both at the same time).
When the Activity is destroyed, the relevant view (AdView or NativeAdView/NativeAd) is properly destroyed.
Yet, Leak Canary reports similar  leaks below whose root cause seems to be a HashMap holding reference to destroyed views:

For WebView banner:

                         D   14:38.372  2726442 bytes retained by leaking objects
                         D   14:38.372  Displaying only 1 leak trace out of 2 with the same signature
                         D   14:38.372  Signature: 91178d655ffcb34658bf9e70d4e86805f1f5cad8
                         D   14:38.372  ┬───
                         D   14:38.372  │ GC Root: Global variable in native code
                         D   14:38.372  │
                         D   14:38.372  ├─ java.util.HashMap instance
                         D   14:38.372  │    Leaking: UNKNOWN
                         D   14:38.372  │    Retaining 1.4 MB in 24300 objects
                         D   14:38.372  │    ↓ HashMap["view"]
                         D   14:38.372  │             ~~~~~~~~
                         D   14:38.372  ├─ com.google.android.gms.ads.nonagon.ad.webview.o instance
                         D   14:38.372  │    Leaking: YES (View.mContext references a destroyed activity)
                         D   14:38.372  │    Retaining 1.4 MB in 24239 objects
                         D   14:38.372  │    View is part of a window view hierarchy
                         D   14:38.372  │    View.mAttachInfo is null (view detached)
                         D   14:38.372  │    View.mWindowAttachCount = 1
                         D   14:38.372  │    mContext instance of <redacted package name>.MainTabActivity with mDestroyed = true
                         D   14:38.372  │    ↓ View.mContext
                         D   14:38.372  ╰→ <redacted package name>.MainTabActivity instance
                         D   14:38.372  ​     Leaking: YES (ObjectWatcher was watching this because <redacted package name>.MainTabActivity received
                         D   14:38.372  ​     Activity#onDestroy() callback and Activity#mDestroyed is true)
                         D   14:38.372  ​     Retaining 585.1 kB in 8632 objects
                         D   14:38.372  ​     key = bafb61be-df07-400f-9322-ac42652c19e4
                         D   14:38.372  ​     watchDurationMillis = 5498
                         D   14:38.372  ​     retainedDurationMillis = 498
                         D   14:38.372  ​     mApplication instance of <redacted package name>.<redateced Application subclass>
                         D   14:38.372  ​     mBase instance of androidx.appcompat.view.ContextThemeWrapper

For Native Ad:

                         D   30:52.422  1785129 bytes retained by leaking objects
                         D   30:52.422  Signature: 91178d655ffcb34658bf9e70d4e86805f1f5cad8
                         D   30:52.422  ┬───
                         D   30:52.422  │ GC Root: Global variable in native code
                         D   30:52.422  │
                         D   30:52.422  ├─ java.util.HashMap instance
                         D   30:52.422  │    Leaking: UNKNOWN
                         D   30:52.422  │    Retaining 1.3 MB in 2525 objects
                         D   30:52.422  │    ↓ HashMap["view"]
                         D   30:52.422  │             ~~~~~~~~
                         D   30:52.422  ├─ com.google.android.gms.ads.nativead.NativeAdView instance
                         D   30:52.422  │    Leaking: YES (View.mContext references a destroyed activity)
                         D   30:52.422  │    Retaining 1.3 MB in 2391 objects
                         D   30:52.422  │    View not part of a window view hierarchy
                         D   30:52.422  │    View.mAttachInfo is null (view detached)
                         D   30:52.422  │    View.mID = R.id.native_ad_view
                         D   30:52.422  │    View.mWindowAttachCount = 1
                         D   30:52.422  │    mContext instance of <redacted package name>.MainTabActivity with mDestroyed = true
                         D   30:52.422  │    ↓ View.mContext
                         D   30:52.422  ╰→ <redacted package name>.MainTabActivity instance
                         D   30:52.422  ​     Leaking: YES (ObjectWatcher was watching this because <redacted package name>.MainTabActivity received
                         D   30:52.422  ​     Activity#onDestroy() callback and Activity#mDestroyed is true)
                         D   30:52.422  ​     Retaining 1.8 MB in 32208 objects
                         D   30:52.422  ​     key = 7bf05d76-263a-4365-a4d5-c6ab4d75da7f
                         D   30:52.422  ​     watchDurationMillis = 5514
                         D   30:52.422  ​     retainedDurationMillis = 513
                         D   30:52.422  ​     mApplication instance of <redacted package name>.<redateced Application subclass>
                         D   30:52.422  ​     mBase instance of androidx.appcompat.view.ContextThemeWrapper


Bubblesoft

unread,
Jun 3, 2024, 9:57:06 AM6/3/24
to Google Mobile Ads SDK Developers
Forgot to mention that I am using com.google.android.gms:play-services-ads:23.1.0, which is the latest version of the AdMob Android SDK.

Mobile Ads SDK Forum Advisor

unread,
Jun 3, 2024, 1:05:21 PM6/3/24
to bubblesof...@gmail.com, google-adm...@googlegroups.com

Hi,

Thank you for contacting us.

I tried in our Google sample project and was unable to replicate the issue. Could you kindly provide the below information privately so we can review it and try to replicate the problem. After doing so, we will be better equipped to offer a solution. 

  • Sample project reproducing the issue 
  • Steps to replicate the problem

If the file(s) you are looking to share are less than 25mb in total you can attach them to this case on your next reply. If you are having trouble attaching your file to this case or if your file(s) are larger than 25mb, kindly provide requested information to us via reply to author option or using the steps below:

1. Navigate to

https://docs.google.com/forms/d/e/1FAIpQLSfkAiXMeYP-fw1W3Z-tT9uwmATEKO5X6S-th0gR2ezdKaaqfg/viewform?usp=pp_url&entry.400550049=Mobile+Ads+SDK&entry.460850823=5004Q00002tJAipQAG&entry.80707362=00237842

2. Fill out all fields, and attach your file(s).

3. Please reply back on this thread when you have uploaded your file(s). Please do not share this link.

This message is in relation to case "ref:!00D1U01174p.!5004Q02tJAip:ref" (ADR-00237842)

Thanks,
 
Google Logo Mobile Ads SDK Team


Bubblesoft

unread,
Jun 4, 2024, 5:53:50 AM6/4/24
to Google Mobile Ads SDK Developers
I could reproduce this issue with the NativeAdvancedExample app.

The reason you could not reproduce it, is that when you start this app, display an ad then hit the back button (or rather gesture),
the system does not destroy the MainActivity (as in calling onDestroy()). It just pauses it (onPause()) which does not cause a leak.
The leak only happens when the Activity is destroyed and in my own app when I do the "back" action, the system always destroys it,
supposedly because it is much more complex than this demo app and  consumes a lot more memory.
I modified the NativeAdvancedExample app and added a "Destroy Activity" button that calls finish() on the MainActivity to destroy it, and the leak appears (see end of message).

I have uploaded the modified NativeAdvancedExample app via the Google form. 
The only modification I made are:

- added the 'Destroy Activity' button to MainActivity
- added leak canary dependency to build.gradle
- disabled the native ad inspector in Manifest so it does not get in the way

To reproduce the problem:

- run the debug version of the app and display an ad
- tap the 'Destroy Activity' button. This calls the MainActivity#onDestroy
- wait for a bit for leak canary to analyze the dump and in the logcat you will see:


      D   55:11.775  ====================================
                         D   55:11.775  HEAP ANALYSIS RESULT
                         D   55:11.775  ====================================
                         D   55:11.775  1 APPLICATION LEAKS
                         D   55:11.775  References underlined with "~~~" are likely causes.
                         D   55:11.775  Learn more at https://squ.re/leaks.
                         D   55:11.775  52706 bytes retained by leaking objects
                         D   55:11.775  Signature: 91178d655ffcb34658bf9e70d4e86805f1f5cad8
                         D   55:11.775  ┬───
                         D   55:11.775  │ GC Root: Global variable in native code
                         D   55:11.775  │
                         D   55:11.775  ├─ java.util.HashMap instance
                         D   55:11.775  │    Leaking: UNKNOWN
                         D   55:11.775  │    Retaining 1.7 MB in 8406 objects
                         D   55:11.775  │    ↓ HashMap["ctx"]
                         D   55:11.775  │             ~~~~~~~
                         D   55:11.775  ╰→ com.google.example.gms.nativeadvancedexample.MainActivity instance
                         D   55:11.775  ​     Leaking: YES (ObjectWatcher was watching this because com.google.example.gms.nativeadvancedexample.MainActivity
                         D   55:11.775  ​     received Activity#onDestroy() callback and Activity#mDestroyed is true)
                         D   55:11.775  ​     Retaining 52.7 kB in 998 objects
                         D   55:11.775  ​     key = 56868e69-221c-41f6-8624-1abe282b7443
                         D   55:11.775  ​     watchDurationMillis = 5265
                         D   55:11.775  ​     retainedDurationMillis = 262
                         D   55:11.775  ​     mApplication instance of android.app.Application
                         D   55:11.775  ​     mBase instance of androidx.appcompat.view.ContextThemeWrapper


Note that the problem also happens with WebView banners, with AdView being leaked instead.


Bubblesoft

unread,
Jun 4, 2024, 11:03:50 AM6/4/24
to Google Mobile Ads SDK Developers
Interestingly, if you change:

   AdLoader.Builder builder = new AdLoader.Builder(this, ADMOB_AD_UNIT_ID);

to:

AdLoader.Builder builder = new AdLoader.Builder(getApplicationContext(), ADMOB_AD_UNIT_ID);

(that is, using the Application Context instead of the Activity Context for the AdLoader)

The reported leak is more detailed an corresponds to the one I reported in first post, making the NativeAdView apparent:

   D   54:06.559  1 APPLICATION LEAKS
                         D   54:06.559  References underlined with "~~~" are likely causes.
                         D   54:06.559  Learn more at https://squ.re/leaks.
                         D   54:06.559  1664381 bytes retained by leaking objects
                         D   54:06.559  Signature: 91178d655ffcb34658bf9e70d4e86805f1f5cad8
                         D   54:06.559  ┬───
                         D   54:06.559  │ GC Root: Global variable in native code
                         D   54:06.559  │
                         D   54:06.559  ├─ java.util.HashMap instance
                         D   54:06.559  │    Leaking: UNKNOWN
                         D   54:06.559  │    Retaining 1.7 MB in 8405 objects
                         D   54:06.559  │    ↓ HashMap["view"]
                         D   54:06.559  │             ~~~~~~~~
                         D   54:06.559  ├─ com.google.android.gms.ads.nativead.NativeAdView instance
                         D   54:06.559  │    Leaking: YES (View.mContext references a destroyed activity)
                         D   54:06.559  │    Retaining 1.7 MB in 8271 objects
                         D   54:06.559  │    View is part of a window view hierarchy
                         D   54:06.559  │    View.mAttachInfo is null (view detached)
                         D   54:06.559  │    View.mWindowAttachCount = 1
                         D   54:06.559  │    mContext instance of com.google.example.gms.nativeadvancedexample.MainActivity with mDestroyed = true
                         D   54:06.559  │    ↓ View.mContext
                         D   54:06.559  ╰→ com.google.example.gms.nativeadvancedexample.MainActivity instance
                         D   54:06.559  ​     Leaking: YES (ObjectWatcher was watching this because com.google.example.gms.nativeadvancedexample.MainActivity
                         D   54:06.559  ​     received Activity#onDestroy() callback and Activity#mDestroyed is true)
                         D   54:06.559  ​     Retaining 49.4 kB in 934 objects
                         D   54:06.559  ​     key = 806db37f-9aad-481d-9c0a-96b1f2566cc8
                         D   54:06.559  ​     watchDurationMillis = 5412
                         D   54:06.559  ​     retainedDurationMillis = 412
                         D   54:06.559  ​     mApplication instance of android.app.Application
                         D   54:06.559  ​     mBase instance of androidx.appcompat.view.ContextThemeWrapper



Mobile Ads SDK Forum Advisor

unread,
Jun 4, 2024, 3:01:19 PM6/4/24
to bubblesof...@gmail.com, google-adm...@googlegroups.com
Hi,

Kindly go through our previous response and provide us a detail of your use case : 
  • Regarding loading either a banner or a native ad - please specify whether you are using different ad containers or a single ad container for either an ad to display.
  • If you are implementing above mentioned scenario please confirm whether you are following Combining Custom-Rendered Native Ad and Banner Ad Requests article.

Bubblesoft

unread,
Jun 4, 2024, 8:16:42 PM6/4/24
to Google Mobile Ads SDK Developers
I have already explained everything you need to know to reproduce this issue, including sending the slightly modified native ad sample (via the Google form), instructions about how to reproduce the issue, and when it happens (Activity destroyed). I have nothing else to add.

Mobile Ads SDK Forum Advisor

unread,
Jun 5, 2024, 1:30:57 AM6/5/24
to bubblesof...@gmail.com, google-adm...@googlegroups.com
Hi,

I will check with our team regarding your issue and one of my team members will reach out to you once we have an update on this. Meanwhile, your patience is highly appreciated.

Bubblesoft

unread,
Jun 5, 2024, 9:14:16 PM6/5/24
to Google Mobile Ads SDK Developers
I also submitted and issue to the example github repo, with even more details for reproducing it:

Mobile Ads SDK Forum Advisor

unread,
Nov 19, 2025, 10:27:27 AM (3 days ago) Nov 19
to bubblesof...@gmail.com, google-adm...@googlegroups.com
 Hi,

The issue has been resolved. Kindly check and confirm the results.


Thanks,
 
Google Logo Mobile Ads SDK Team

Feedback
How was our support today?

rating1    rating2    rating3    rating4    rating5
[2025-11-19 15:26:31Z GMT] This message is in relation to case "ref:!00D1U01174p.!5004Q02tJAip:ref" (ADR-00237842)



Reply all
Reply to author
Forward
0 new messages