My favorites | Sign in
Project Home Issues
New issue   Search
for
  Advanced search   Search tips   Subscriptions
Issue 8596: MapView Memory Leak
36 people starred this issue and may be notified of changes. Back to list
Status:  Accepted
Owner:  ----


Sign in to add a comment
 
Reported by [email protected], Sep 11, 2015
Support library 23.0.1 (happens from 22...)
Android 5.1.1, not sure if it hapens in others.

I´m getting a memory leak (thanks to leak canary https://github.com/square/leakcanary) with MapView inside a Fragment.

I call mapView.onResume, onCreate, onPause, onDestroy, onLowMemory on each fragment event.

My Layout looks like:

```
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/status_layout_main"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:baselineAligned="false">

    <com.google.android.gms.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/status_layout_assigned" />

...

```

There´s a related issue here http://stackoverflow.com/questions/19061488/android-mapview-v2-context-issues-and-memory-leak.

I uploaded the heap_dump and a memory leak description.
Here´s the head_dump.htprof https://www.dropbox.com/s/t6l4mt2vdavdb1v/heap_dump_3.hprof?dl=0




From here https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=185902
memory leak description
22.9 KB   View   Download
Sep 14, 2015
Project Member #1 [email protected]
(No comment was entered for this change.)
Labels: ApiType-Android2 Type-Defect
Sep 14, 2015
Project Member #2 [email protected]
Thanks for the report!

Are you using the My Location layer by any chance? (See https://code.google.com/p/gmaps-api-issues/issues/detail?id=8111 ) Could you please try the workaround mentioned in that issue (disabling the my location layer in onDestroy or in onPause.)
Status: NeedsMoreInfo
Sep 16, 2015
#3 [email protected]
Every time I need to do something I get the googleMap with getMapAsync and then, inside use it.
That´s wrong? should I save the googleMap Instance and use it everywhere and then set as null in onDestroy? 

Ex:

mapView.getMapAsync(googleMap -> googleMap.setMyLocationEnabled(true));
Nov 19, 2015
#4 [email protected]
Hello, I get same leak. Each time I switch tabs to the Fragment tab that I have 

    <com.google.android.gms.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

device memory drops by about 50MB! I have implemented also map.setMyLocationEnabled(false) in onPause of the Fragment.

My fragment that has the map extends Fragment (can't extend the MapFragment) like this:

public class FragmentMap extends Fragment implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener,
        OnMapReadyCallback {

Thanks
Nov 20, 2015
#5 [email protected]
Hello,

I did one more test using the the https://github.com/googlemaps/android-samples ApiDemos, where in the MapInPagerDemoActivity, in MyAdapter, I did this change:

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return new FragmentMap().newInstance(position);
                case 1:
                case 2:
                    return new TextFragment();
//                case 3:
//                    return new TextFragment();
//                case 4:
//                    return SupportMapFragment.newInstance();
                default:
                    return null;
            }
        }

where FragmentMap is as follows:

public class FragmentMap extends Fragment implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener,
        OnMapReadyCallback {...}

There is still leakage, going in the most right tab, and coming back to the fragment map, even if map.setMyLocationEnabled(false);

Using:

    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.google.android.gms:play-services:8.1.0'

Thanks
Nov 20, 2015
#6 [email protected]
Similar leak as in #4, #5, but now with:

    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.google.android.gms:play-services:8.3.0'

Dec 6, 2015
Project Member #7 [email protected]
Can you share the LeakCanary trace from the lastest version of Google Play Services?

We fixed the 'my location layer' Activity leak previously: https://code.google.com/p/gmaps-api-issues/issues/detail?id=8111




Dec 6, 2015
#8 [email protected]
I also had same memory leak with 8.3, we are currently fixing it with the setMyLocationEnabled(false). It doesn't appear to be fixed
Dec 10, 2015
#10 [email protected]
I was able to get a leak log with a KitKat phone (thanks to leakcanary https://github.com/square/leakcanary):

Using #5 with the #6 modification, please find the leak snapshot:

12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: In com.example.mapdemo:1.0:1.
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * com.example.mapdemo.MapInPagerDemoActivity has leaked:
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * GC ROOT com.google.android.gms.location.internal.zzk$zzc.zzaLV
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * references com.google.android.gms.location.internal.zzk$zzb.zzaLX
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * references com.example.mapdemo.FragmentMap.mapView
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * references com.google.android.gms.maps.MapView.mContext
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * leaks com.example.mapdemo.MapInPagerDemoActivity instance
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * Reference Key: 9a962b42-ea48-48ae-a323-603de5f144d8
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * Device: HUAWEI Huawei HUAWEI Y550-L01 Y550-L01
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * Android Version: 4.4.4 API: 19 LeakCanary: 1.3.1
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * Durations: watch=5379ms, gc=179ms, heap dump=877ms, analysis=21731ms
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * Details:
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * Instance of com.google.android.gms.location.internal.zzk$zzc
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   zzaLV = com.google.android.gms.location.internal.zzk$zzb [id=0x42271230]
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   mDescriptor = java.lang.String [id=0x42274ee0]
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   mOwner = com.google.android.gms.location.internal.zzk$zzc [id=0x422758f8]
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   mObject = 1627806640
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: * Instance of com.google.android.gms.location.internal.zzk$zzb
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   zzaLX = com.example.mapdemo.FragmentMap [id=0x42414398]
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   mQueue = android.os.MessageQueue [id=0x4224cd90]
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   mCallback = null
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   mLooper = android.os.Looper [id=0x4224cd78]
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   mMessenger = null
12-10 15:36:37.457 937-3993/com.example.mapdemo D/LeakCanary: |   mAsynchronous = false

Dec 10, 2015
#11 [email protected]
And some more (different?):

1. 

12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: In com.example.mapdemo:1.0:1.
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * com.example.mapdemo.MapInPagerDemoActivity has leaked:
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * GC ROOT com.google.android.gms.location.internal.zzk$zzc.zzaLV
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * references com.google.android.gms.location.internal.zzk$zzb.zzaLX
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * references com.example.mapdemo.FragmentMap.mGoogleApiClient
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * references com.google.android.gms.internal.zzmg.mContext
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * leaks com.example.mapdemo.MapInPagerDemoActivity instance
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * Reference Key: bd5e9fc1-49a6-496b-8855-a5db4e8895e2
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * Device: HUAWEI Huawei HUAWEI Y550-L01 Y550-L01
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * Android Version: 4.4.4 API: 19 LeakCanary: 1.3.1
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * Durations: watch=5343ms, gc=213ms, heap dump=1601ms, analysis=23065ms
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * Details:
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * Instance of com.google.android.gms.location.internal.zzk$zzc
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   zzaLV = com.google.android.gms.location.internal.zzk$zzb [id=0x42822e18]
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   mDescriptor = java.lang.String [id=0x42274ee0]
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   mOwner = com.google.android.gms.location.internal.zzk$zzc [id=0x42822dd0]
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   mObject = 1623503240
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: * Instance of com.google.android.gms.location.internal.zzk$zzb
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   zzaLX = com.example.mapdemo.FragmentMap [id=0x427a5ae8]
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   mQueue = android.os.MessageQueue [id=0x4224cd90]
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   mCallback = null
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   mLooper = android.os.Looper [id=0x4224cd78]
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   mMessenger = null
12-10 15:59:28.177 937-3176/com.example.mapdemo D/LeakCanary: |   mAsynchronous = false

Dec 10, 2015
Project Member #12 [email protected]
Are you seeing the same issue with the original code in MapInPagerDemoActivity? (Ie. using MapFragment directly?)

It sounds like it might be an issue in your custom Fragment. Are you forwarding all calls to super in the lifecycle callbacks?
Are you holding onto any maps-related objects in your fragment past its lifecycle?
Dec 15, 2015
#14 [email protected]
Here is another leak trace (using the example of posts #5 and #6), hope it's helpful:

12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: In com.example.mapdemo:1.0:1.
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * com.example.mapdemo.MapInPagerDemoActivity has leaked:
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * GC ROOT static com.google.maps.api.android.lib6.gmm6.h.q.j
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.h.q.f
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.h.g.f
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.h.t.g
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * references java.util.concurrent.CopyOnWriteArrayList.elements
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * references array java.lang.Object[].[0]
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.m.cy.g
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.m.bf.k
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.c.y.mParent
12-15 20:35:39.103 17227-20885/com.example.mapdemo D/LeakCanary: * references android.widget.FrameLayout.mParent
12-15 20:35:39.113 17227-20885/com.example.mapdemo D/LeakCanary: * references com.google.android.gms.maps.MapView.mContext
12-15 20:35:39.113 17227-20885/com.example.mapdemo D/LeakCanary: * leaks com.example.mapdemo.MapInPagerDemoActivity instance


Dec 15, 2015
#15 [email protected]
One more slighlty different leak trace:

12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: In com.example.mapdemo:1.0:1.
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * com.example.mapdemo.MapInPagerDemoActivity has leaked:
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * GC ROOT static com.google.maps.api.android.lib6.gmm6.h.q.j
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.h.q.f
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.h.g.g
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * references java.util.ArrayList.array
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * references array java.lang.Object[].[0]
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.m.cy.g
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.m.bf.k
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.c.y.mParent
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * references android.widget.FrameLayout.mParent
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * references com.google.android.gms.maps.MapView.mContext
12-15 21:37:32.552 10110-11182/com.example.mapdemo D/LeakCanary: * leaks com.example.mapdemo.MapInPagerDemoActivity instance
Dec 15, 2015
#16 [email protected]
With regards to your post #12:

> Are you seeing the same issue with the original code in MapInPagerDemoActivity? (Ie. using MapFragment directly?)
It sounds like it might be an issue in your custom Fragment. Are you forwarding all calls to super in the lifecycle callbacks?
Are you holding onto any maps-related objects in your fragment past its lifecycle?


That original code in MapInPagerDemoActivity doesn't apply here as it uses just:

"return SupportMapFragment.newInstance();"

i.e. there is no use of mapView in xml:

<com.google.android.gms.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>


Dec 22, 2015
#17 [email protected]
Hello, is there any bug confirmation?

Attached is also a simplified version of the FragmentMap code along the #5, and #6 messages:

FragmentMap.java:

package com.example.mapdemo;

import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.OnMapReadyCallback;

public class FragmentMap extends Fragment implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener,
        OnMapReadyCallback {

    MapView mapView;

    public static FragmentMap newInstance(int idx) {
        FragmentMap fragment = new FragmentMap();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.pager_map, container, false);

        mapView = (MapView) view.findViewById(R.id.mapView);
        mapView.onCreate(savedInstanceState);
        mapView.getMapAsync(this);

        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Bundle args = getArguments();
        if (args != null) {
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
    }

    @Override
    public void onConnected(Bundle connectionHint) {
    }

    @Override
    public void onConnectionSuspended(int cause) {
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
    }

    @Override
    public void onLocationChanged(Location location) {
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapView.onLowMemory();
    }

    @Override
    public void onResume() {
        super.onResume();

        if (mapView != null)
            mapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();

        if (mapView != null)
            mapView.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (mapView != null)
            mapView.onDestroy();
    }
}


pager_map.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.google.android.gms.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>


Leak:

12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * com.example.mapdemo.MapInPagerDemoActivity has leaked:
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * GC ROOT static com.google.maps.api.android.lib6.gmm6.h.q.j
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.h.q.f
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.h.g.f
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.h.t.g
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references java.util.concurrent.CopyOnWriteArrayList.elements
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references array java.lang.Object[].[0]
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.m.cy.g
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.m.bf.k
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references com.google.maps.api.android.lib6.gmm6.c.y.mParent
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references android.widget.FrameLayout.mParent
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * references com.google.android.gms.maps.MapView.mContext
12-22 11:11:53.458 5081-6926/com.example.mapdemo D/LeakCanary: * leaks com.example.mapdemo.MapInPagerDemoActivity instance


Jan 5, 2016
Project Member #18 [email protected]
Thanks for the report. Please let us know if there's any other details you can add.

Have you been able to reproduce this on any other device than the "HUAWEI Y550-L01"?
Status: Accepted
Labels: Internal-26413616
Jan 5, 2016
Project Member #19 [email protected]
 Issue 8155  has been merged into this issue.
Jan 20, 2016
#20 [email protected]
Yes reproduced in Nexus 6, API 23 thanks to LeakCanary (https://github.com/square/leakcanary):


* AAAAA.BBBBB has leaked:
* GC ROOT static com.google.maps.api.android.lib6.gmm6.h.q.j
* references com.google.maps.api.android.lib6.gmm6.h.q.f
* references com.google.maps.api.android.lib6.gmm6.h.g.f
* references com.google.maps.api.android.lib6.gmm6.h.t.g
* references java.util.concurrent.CopyOnWriteArrayList.elements
* references array java.lang.Object[].[0]
* references com.google.maps.api.android.lib6.gmm6.m.cy.g
* references com.google.maps.api.android.lib6.gmm6.m.bf.k
* references com.google.maps.api.android.lib6.gmm6.c.y.mParent
* references android.widget.FrameLayout.mParent
* references com.google.android.gms.maps.MapView.mContext
* leaks AAAAA.BBBBB instance
* Retaining: 26 MB.
* Reference Key: 1a047032-acb7-4ad7-993a-d066c7530128
* Device: motorola google Nexus 6 shamu
* Android Version: 6.0.1 API: 23 LeakCanary: 1.4-beta1 02804f3
* Durations: watch=6283ms, gc=187ms, heap dump=8934ms, analysis=77315ms
* Details:
* Class com.google.maps.api.android.lib6.gmm6.h.q
|   static $staticOverhead = byte[16]@315894273 (0x12d42a01)

Sign in to add a comment

Powered by Google Project Hosting