21

I have a ListView and I would expect it to be cleared from memory when the activity finishes. However, it appears that it is leaking. When I check the Memory Dump, and get the pathToGC for the ListView I get the following,

Class Name                                                          | Shallow Heap | Retained Heap 
android.widget.ExpandableListView @ 0x4063e560                      |          768 |        39,904 
|- list, mList com.hitpost.TeamChooser @ 0x405f92e8                 |          176 |         1,648 
|  '- mOuterContext android.app.ContextImpl @ 0x40657368            |          160 |           304 
|     '- mContext android.media.AudioManager @ 0x40662600           |           40 |           168 
|        '- this$0 android.media.AudioManager$1 @ 0x406626b0 Unknown|           24 |            24 

I see this same context leaking on a lot of of my ListView's. The trick is that, I am not using AudioManager anywhere in my app at all, no sound coming from the app at all. Please help, it's driving me crazy. Obviously trying to figure out why this is happening and what could be the root issue?

Trikaldarshiii
  • 11,174
  • 16
  • 67
  • 95
Leo
  • 4,652
  • 6
  • 32
  • 42
  • Well yes had static variables, just removed all of them from one of the activities that has a ListView. But the same context is still leaking. – Leo Jun 22 '11 at 19:33
  • Its nothing to do with the ListView and everything to do with the AudioManager. What are you doing with the AudioManager? – cyngus Jun 22 '11 at 19:55
  • 1
    As I said AudioManager literally appears absolutely no where in my code, or even in any of the libraries that I am using. Thus my continued confusion – Leo Jun 22 '11 at 19:57
  • 3
    Did you ever happen to figure out what causes this? – Nick Campion Feb 08 '12 at 08:58
  • 2
    I am facing the same issue. One of my activities stays in memory even after it is destroyed. MAT shows that AudioManager is holding it and I am not using AudioManager anywhere. Any ideas on this? – Sameer Mar 12 '12 at 05:05
  • 2
    I have this problem as well... any solution? realy annoying... a lot of my Activities stays up with for no reason cause of this problem – Mario Lenci Mar 15 '12 at 16:42
  • Just to clarify, when using the memory analyser did you "exclude weak and soft references"? You could be holding a reference to the context somewhere else which is keeping all its views alive (making this a red herring) – smith324 Mar 18 '12 at 16:02
  • Got this problem now after 6 years. – Denny Apr 30 '17 at 00:24

8 Answers8

8

Not related to OP's leak, but for people who come in here because of AudioManager causing leak:

If you see this leak because you are using VideoView, probably is because of this bug: https://code.google.com/p/android/issues/detail?id=152173

VideoView never release AudioManager if video being loaded.

the fix is, as mentioned in the link, create VideoView manually using ApplicationContext.

Edit: this work around will work, until... if the video decoder says the video has an encoding problem. VideoView tries to pop up a AlertDialog using application context. Than a crash happens.

The only work around I can think is to keep creating video view using activity context, and in activity.onDestroy, set AudioManager's mContext to application context using reflection.

Note: have to get the AudioManager using activity.getSystemService(Context.AUDIO_SERVICE) rather than activity.getApplicationContext.getSystemService(Context.AUDIO_SERVICE), since AudioManager is an member variable of Context (you will get wrong instance of AudioManager if you get it from application context).

At last, you may wonder why a member variable (AudioManager) is preventing the class (Activity) to being garbage collected. From the memory analyzer, it shows AudioManager is owned by native stack. So AudioManager somehow did not clean itself properly.

Helin Wang
  • 4,002
  • 1
  • 30
  • 34
5

There are several references to AudioManager in your code that you don't create actively. E.g. each clickable View might have one to play onClick sounds [source]. I guess that is the link.

The code looks like it would not create references to AudioManager if you disable the click sounds in your Settings. You could try that and check if there is still a leak.

The reason for your leak might be that you are holding onto some View object in your ListView (Adapter?) code. If you keep them around then you might have a View that has an AudioManager reference and that keeps a Context reference)

zapl
  • 63,179
  • 10
  • 123
  • 154
  • As I think most of the apps out there i have the same issue. – Mario Lenci Sep 27 '12 at 13:20
  • 2
    I don't think the answer should be revolving around Context. `AudioManager` is a singleton class and a system class. The garbage collector knows this and performs the proper collection accordingly. All you need to do is do a GC call before you dump the memory. – redDragonzz Nov 29 '13 at 07:21
4

I had this same issue but it went away after following the below advice.

Mr Guy recommends not doing heap dumps in the debugger and causing a few GCs before getting the dump. https://groups.google.com/forum/?fromgroups=#!topic/android-developers/ew6lfZUH0z8

Sean Moore
  • 181
  • 2
  • 4
1

You can use application context to avoid leaks in this case. I don't know why but when I started to use application context the problem was gone.

Bracadabra
  • 3,609
  • 3
  • 26
  • 46
0

The most common reason that I found in my application was due to initializing some components via the XML file. When you do that, the Activity Context gets injected but sometimes all you need is an ApplicationContext. With respect to the Web View in Android, this technique greatly helped me a lot.

redDragonzz
  • 1,543
  • 2
  • 15
  • 33
0

I would like to share my experience regarding the same issue, I was keeping some Activity in stack by default and not finishing them.

For those activity, I was getting same as mentioned above in hprof report.

Once I finished no longer used Activities, above references did not come. Just finish your activity when it is no longer required, then this issue will be resolved.

Abhishek Jain
  • 6,296
  • 7
  • 26
  • 34
0

This is a very basic activity that replicates the issue (on Android 4.0.3 at least)

public class MainActivity extends Activity {

    int image[];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.activity_main);
        image = new int[1000 * 1500 * 4];
    }
}

As you can see there are no Views or Layots associated with activity, also I set "Silent" profile in system Sound Settings and turned off "Vibrate on touch".

Now, after few (5-7 depending on your heapSize) restarts this activity generates the java.lang.OutOfMemoryError on trying to create new array.

07-27 19:54:10.160  22542-22542/? D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 1% free 56040K/56391K, paused 25ms
07-27 19:54:10.190  22542-22542/? D/dalvikvm﹕ GC_BEFORE_OOM freed 23449K, 43% free 32591K/56391K, paused 30ms
07-27 19:54:10.260  22542-22543/? D/dalvikvm﹕ GC_CONCURRENT freed 0K, 1% free 56029K/56391K, paused 3ms+3ms
07-27 19:54:11.850  22542-22542/? D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 1% free 56040K/56391K, paused 20ms
07-27 19:54:11.880  22542-22542/? D/dalvikvm﹕ GC_BEFORE_OOM freed <1K, 1% free 56040K/56391K, paused 29ms
... Out of memory on a 24000016-byte allocation.

Dumping .hprof I also saw 2 activities, one of them is being held by AudioManager.

Calling the "Update Heap" and then Collect Garbage in Android Device Monitor really does remove the activity from memory, that is what the logcat states on this procedure

07-27 19:44:23.150        85-85/? I/DEBUG﹕ #06  pc 000382cc  /system/lib/libdvm.so (dvmCollectGarbageInternal(GcSpec const*)+1204)

I have also tried to build the release version of the apk and it behaves the same. So it is not the debugger holding the reference.

This seems to me as a bug in Android. The workaround would be to explicitly call the image = null in OnStop() or onFinish() of the activity. This of course is not convenient.

Kurovsky
  • 1,081
  • 10
  • 25
-4

If your application crashes for memory leak, then you can avoid this crash using try - catch(java.lang.outofmemory). The fact is that GC is called by JVM itself, so programer has no control on this. You can install your application in SD card, in this case SD card memory will be used. Memory leak will not occur.

Just go to your manifest file, there must be version no. version name, there also must be " Install Location" , make it "preferExternal".

Braiam
  • 1
  • 11
  • 47
  • 78
Santanu
  • 141
  • 2
  • 11
  • I don't think this answers my question. – Sameer Mar 13 '12 at 13:35
  • @santanu, _You can install your application in SD card, in this case SD card memory will be used. Memory leak will not occur_. What the hell? –  Mar 17 '12 at 23:16
  • 1
    @haibison a memory leak is something [different](http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html). It's about RAM being unnecessarily used and has nothing to do with SD cards. – zapl Mar 18 '12 at 11:13
  • @zapl, Thanks :-) I understand that. I'm just confused about his message. –  Mar 18 '12 at 12:10
  • @haibison Oops, it's a quote. I was already wondering wth you all had about sd card – zapl Mar 18 '12 at 12:18