Firebase-android-sdk: Memory leak in FirebaseInAppMessagingDisplay

Created on 2 Jun 2019  Β·  8Comments  Β·  Source: firebase/firebase-android-sdk

[READ] Step 1: Are you in the right place?

Yes

[REQUIRED] Step 2: Describe your environment

  • Android Studio version: 3.5 Beta 3
  • Firebase Component: firebase-inappmessaging-display
  • Component version: 17.1.1

[REQUIRED] Step 3: Describe the problem

Steps to reproduce:

Install LeakCanary and Firebase In App Messaging in the project. Launch the app. Wait for the leak notification to appear.

LeakCanary is reporting a memory leak for FirebaseInAppMessagingDisplay. Here is part of the leak report:

 ┬
 β”œβ”€ android.provider.FontsContract
 β”‚    Leaking: NO (it's a GC root and a class is never leaking)
 β”‚    ↓ static FontsContract.sContext
 β”œβ”€ com.example.app.App
 β”‚    Leaking: NO (Application is a singleton)
 β”‚    ↓ App.mActivityLifecycleCallbacks
 β”‚          ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 β”œβ”€ java.util.ArrayList
 β”‚    Leaking: UNKNOWN
 β”‚    ↓ ArrayList.elementData
 β”‚                ~~~~~~~~~~~
 β”œβ”€ java.lang.Object[]
 β”‚    Leaking: UNKNOWN
 β”‚    ↓ array Object[].[3]
 β”‚                     ~~~
 β”œβ”€ com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay
 β”‚    Leaking: UNKNOWN
 β”‚    ↓ FirebaseInAppMessagingDisplay.firebaseInAppMessagingDisplay
 β”‚                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 β”œβ”€ com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay$1
 β”‚    Leaking: UNKNOWN
 β”‚    Anonymous class implementing com.google.firebase.inappmessaging.FirebaseInAppMessagingDisplay
 β”‚    ↓ FirebaseInAppMessagingDisplay$1.val$activity
 β”‚                                      ~~~~~~~~~~~~
 β•°β†’ com.example.app.ui.main.MainActivity
 ​     Leaking: YES (RefWatcher was watching this and MainActivity#mDestroyed is true)
 (removed the rest of the leak dump)

Looking into the Firebase code myself, I think this is the cause of the leak. An anonymous class is created which references the activity parameter. This class is then saved in the variable firebaseInAppMessagingDisplay, which is never cleared when the activity is destroyed.

inappmessaging

Most helpful comment

This has quite some impact on all apps using FirebaseInAppMessaging. Would be great to get some feedback whether someone is actively looking into it. πŸ™

All 8 comments

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

Here is a workaround using reflection which fixes the issue for now:

import android.app.Activity
import android.app.Application
import android.os.Bundle
import com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay

class App : Application() {

    private var firebaseInAppMessagingCallback: FirebaseInAppMessagingDisplay? = null

    override fun onCreate() {
        super.onCreate()

        // TODO: Add proguard rules for reflection.

        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
            override fun onActivityDestroyed(activity: Activity) {
                firebaseInAppMessagingCallback?.let { callback ->
                    val field = callback.javaClass.getDeclaredField("firebaseInAppMessagingDisplay")
                    field.isAccessible = true
                    field.set(callback, null)
                }
            }

            override fun onActivityPaused(activity: Activity) {}
            override fun onActivityResumed(activity: Activity) {}
            override fun onActivityStarted(activity: Activity) {}
            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
            override fun onActivityStopped(activity: Activity) {}
            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
        })
    }

    override fun registerActivityLifecycleCallbacks(callback: ActivityLifecycleCallbacks?) {
        super.registerActivityLifecycleCallbacks(callback)
        if (callback is FirebaseInAppMessagingDisplay) {
            firebaseInAppMessagingCallback = callback
        }
    }
}

Any update on this issue?

This has quite some impact on all apps using FirebaseInAppMessaging. Would be great to get some feedback whether someone is actively looking into it. πŸ™

Same here!

@Thomas-Vos super helpful above, let me see what I can do

This appears to be fixed now. Thanks!

same here ! so when will this fix be released officially on Maven repo ?

Was this page helpful?
0 / 5 - 0 ratings