Skip to content

[Android] Leakcanary complains several memory leak from FlutterView, FlutterFragment #36898

@yjoo9317

Description

@yjoo9317

Steps to Reproduce

  1. Flutter module has been added to existing app
  2. Launch simple flutter view (just text + button)
  3. Close the view
  4. Wait for leakcanary notification

Since I am not a leakcanary expert,
I am wondering if you guys have seen these before
or whether do you think the following leak cases are already known or rather they are coming from my app code.

I've checked my code and I believe that I don't have any surviving references which result to having retained instances. (But who knows..)

Logs

  1. FlutterView (TextInputPlugin)
LeakingInstance(referenceKey=037e73b3-4448-4ae2-baed-2de1569f114d, referenceName=, 
instanceClassName=io.flutter.embedding.android.FlutterView, watchDurationMillis=5273, 
exclusionStatus=null, 
leakTrace=
┬
├─ android.net.ConnectivityThread
│    Leaking: NO (it's a GC root)
│    Thread name: 'ConnectivityThread'
│    ↓ thread ConnectivityThread.contextClassLoader
├─ dalvik.system.PathClassLoader
│    Leaking: NO (Object[]↓ is not leaking and Classloader never leaking)
│    ↓ PathClassLoader.runtimeInternalObjects
├─ java.lang.Object[]
│    Leaking: NO (FlutterDelegate↓ is not leaking)
│    ↓ array Object[].[461]
├─ com.myapp.flutter.FlutterDelegate
│    Leaking: NO (a class is never leaking)
│    ↓ static FlutterDelegate.instance
│                             ~~~~~~~~
├─ com.myapp.flutter.FlutterDelegate
│    Leaking: UNKNOWN
│    ↓ FlutterDelegate.controlChannel
│                      ~~~~~~~~~~~~~~
├─ io.flutter.plugin.common.MethodChannel
│    Leaking: UNKNOWN
│    ↓ MethodChannel.messenger
│                    ~~~~~~~~~
├─ io.flutter.embedding.engine.dart.DartExecutor
│    Leaking: UNKNOWN
│    ↓ DartExecutor.messenger
│                   ~~~~~~~~~
├─ io.flutter.embedding.engine.dart.DartMessenger
│    Leaking: UNKNOWN
│    ↓ DartMessenger.messageHandlers
│                    ~~~~~~~~~~~~~~~
├─ java.util.HashMap
│    Leaking: UNKNOWN
│    ↓ HashMap.table
│              ~~~~~
├─ java.util.HashMap$Node[]
│    Leaking: UNKNOWN
│    ↓ array HashMap$Node[].[19]
│                           ~~~~
├─ java.util.HashMap$Node
│    Leaking: UNKNOWN
│    ↓ HashMap$Node.value
│                   ~~~~~
├─ io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler
│    Leaking: UNKNOWN
│    ↓ MethodChannel$IncomingMethodCallHandler.handler
│                                              ~~~~~~~
├─ io.flutter.embedding.engine.systemchannels.TextInputChannel$1
│    Leaking: UNKNOWN
│    Anonymous class implementing io.flutter.plugin.common.MethodChannel$MethodCallHandler
│    ↓ TextInputChannel$1.this$0
│                         ~~~~~~
├─ io.flutter.embedding.engine.systemchannels.TextInputChannel
│    Leaking: UNKNOWN
│    ↓ TextInputChannel.textInputMethodHandler
│                       ~~~~~~~~~~~~~~~~~~~~~~
├─ io.flutter.plugin.editing.TextInputPlugin$1
│    Leaking: UNKNOWN
│    Anonymous class implementing io.flutter.embedding.engine.systemchannels.TextInputChannel$TextInputMethodHandler
│    ↓ TextInputPlugin$1.this$0
│                        ~~~~~~
├─ io.flutter.plugin.editing.TextInputPlugin
│    Leaking: UNKNOWN
│    ↓ TextInputPlugin.mView
│                      ~~~~~
╰→ io.flutter.embedding.android.FlutterView
​     Leaking: YES (RefWatcher was watching this)
, retainedHeapSize=null)
  1. FlutterFragment
LeakingInstance(referenceKey=63604ca7-d810-4d31-b38b-441e9a940ed1, referenceName=,
instanceClassName=io.flutter.embedding.android.FlutterFragment, watchDurationMillis=5272,
exclusionStatus=null, 
leakTrace=
┬
├─ android.net.ConnectivityThread
│    Leaking: NO (it's a GC root)
│    Thread name: 'ConnectivityThread'
│    ↓ thread ConnectivityThread.contextClassLoader
├─ dalvik.system.PathClassLoader
│    Leaking: NO (Object[]↓ is not leaking and Classloader never leaking)
│    ↓ PathClassLoader.runtimeInternalObjects
├─ java.lang.Object[]
│    Leaking: NO (FlutterDelegate↓ is not leaking)
│    ↓ array Object[].[461]
├─ com.myapp.flutter.FlutterDelegate
│    Leaking: NO (a class is never leaking)
│    ↓ static FlutterDelegate.instance
│                             ~~~~~~~~
├─ com.myapp.flutter.FlutterDelegate
│    Leaking: UNKNOWN
│    ↓ FlutterDelegate.flutterEngine
│                      ~~~~~~~~~~~~~
├─ io.flutter.embedding.engine.FlutterEngine
│    Leaking: UNKNOWN
│    ↓ FlutterEngine.pluginRegistry
│                    ~~~~~~~~~~~~~~
├─ io.flutter.embedding.engine.FlutterEnginePluginRegistry
│    Leaking: UNKNOWN
│    ↓ FlutterEnginePluginRegistry.activityAwarePlugins
│                                  ~~~~~~~~~~~~~~~~~~~~
├─ java.util.HashMap
│    Leaking: UNKNOWN
│    ↓ HashMap.table
│              ~~~~~
├─ java.util.HashMap$Node[]
│    Leaking: UNKNOWN
│    ↓ array HashMap$Node[].[8]
│                           ~~~
├─ java.util.HashMap$Node
│    Leaking: UNKNOWN
│    ↓ HashMap$Node.value
│                   ~~~~~
├─ io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry$ShimRegistrarAggregate
│    Leaking: UNKNOWN
│    ↓ ShimPluginRegistry$ShimRegistrarAggregate.activityPluginBinding
│                                                ~~~~~~~~~~~~~~~~~~~~~
├─ io.flutter.embedding.engine.FlutterEnginePluginRegistry$FlutterEngineActivityPluginBinding
│    Leaking: UNKNOWN
│    ↓ FlutterEnginePluginRegistry$FlutterEngineActivityPluginBinding.activity
│                                                                     ~~~~~~~~
├─ com.myapp.flutter.MyFlutterActivity
│    Leaking: YES (MyFlutterActivity#mDestroyed is true)
│    ↓ MyFlutterActivity.mFragments
├─ androidx.fragment.app.FragmentController
│    Leaking: YES (MyFlutterActivity↑ is leaking)
│    ↓ FragmentController.mHost
├─ androidx.fragment.app.FragmentActivity$HostCallbacks
│    Leaking: YES (FragmentController↑ is leaking)
│    ↓ FragmentActivity$HostCallbacks.mFragmentManager
├─ androidx.fragment.app.FragmentManagerImpl
│    Leaking: YES (FragmentActivity$HostCallbacks↑ is leaking)
│    ↓ FragmentManagerImpl.mAdded
├─ java.util.ArrayList
│    Leaking: YES (FragmentManagerImpl↑ is leaking)
│    ↓ ArrayList.elementData
├─ java.lang.Object[]
│    Leaking: YES (ArrayList↑ is leaking)
│    ↓ array Object[].[0]
╰→ io.flutter.embedding.android.FlutterFragment
​     Leaking: YES (RefWatcher was watching this and FlutterFragment#mFragmentManager is null)
, retainedHeapSize=null)

flutter doctor complains no issue.

[✓] Flutter (Channel dev, v1.8.1, on Mac OS X 10.14.5 18F132, locale en-US)
    • Flutter version 1.8.1 at /Users/myhome/Library/flutter/1.8.1-dev
    • Framework revision d3eee57c0b (2 weeks ago), 2019-07-08 11:04:24 -0700
    • Engine revision 3c51a7bfff
    • Dart version 2.5.0 (build 2.5.0-dev.0.0 b5aeaa6796)
...

Metadata

Metadata

Assignees

Labels

a: existing-appsIntegration with existing apps via the add-to-app flowplatform-androidAndroid applications specifically

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions