开发者

How to tell if an Android app is actually leaking memory?

Whilst developing an application, I noticed that it eventually crashed because the JVM could not allocate any more memory. Using the the adb shell dumpsys meminfo command, I could see that the allocated native heap grew whilst switching activities until it approached 16M, when it crashed. I believe I've now corrected the code to stop this happening, but I notice that the figures returned by ..meminfo vary a bit and in general seem to rise slightly now.

Basically I'm not sure whether they should return to the same values when I start and stop an application. I have these figures and I'm not sure whether they signify that I have a memory leak or not:

At home screen, application in memory (PID seen in DDMS), but not running

adb shell dumpsys meminfo (relevant PID) gives:

                    native   dalvik    other    total
            size:     5248     4039      N/A     9287
       allocated:     5227     3297      N/A     8524
            free:       12      742      N/A      754
           (Pss):     2183     3534     1726     7443
  (shared dirty):     1976     4640      876     7492
    (priv dirty):     2040     1664      940     4644

Application started from home screen, acivities started were :

splash screen -> select mode -> Activity 1, then all backed out using the back button, till back at home screen

meminfo now:

                    native   dalvik    other    total
            size:     5572     4231      N/A     9803
       allocated:     5497     3153      N/A     8650
            free:       74     1078      N/A     1152
           (Pss):     2479     3614     1742     7835
  (shared dirty):     1976     4632      876     7484
    (priv dirty):     2336     1740      956     5032

process repeated:

                    native   dalvik    other    total
            size:     5696     4231      N/A     9927
       allocated:     5211     2949      N/A     8160
            free:      392     1282      N/A     1674
           (Pss):     2515     3713     1742     7970
  (shared dirty):     1976     4632      876     7484
    (priv dirty):     2372     1840      956     5168

Eclipse Memory Analyzer Tool (which I don't find all that informative) reports on the following 'leak suspects':

3,143 instances of "java.lang.Class", loaded by "<system class loader>" occupy 736,760 (35.69%) bytes. 

Biggest instances:

class com.ibm.icu4jni.util.Resources$DefaultTimeZones @ 0x40158fe0 - 165,488 (8.02%) bytes. 
class android.text.Html$HtmlParser @ 0x400eebd8 - 126,592 (6.13%) bytes. 
class com.google.googlenav.proto.GmmMessageTypes @ 0x43d183d8 - 56,944 (2.76%) bytes. 
class org.apache.harmony.security.fortress.Services @ 0x40071430 - 51,456 (2.49%) bytes. 
class android.content.res.Resources @ 0x4004df38 - 33,584 (1.63%) bytes. 
class android.text.AutoText @ 0x400f23c8 - 31,344 (1.52%) bytes. 



Keywords
java.lang.Class


Details »
  Problem Suspect 2
8,067 instances of "java.lang.String", loaded by "<system class loader>" occupy 497,304 (24.09%) bytes. 

Keywords
java.lang.String


Details »
  Problem Suspect 3
54 instances of "org.bouncycastle.jce.provider.X509CertificateObject", loaded by "<system class loader>" occupy 256,024 (12.40%) bytes. These instances are referenced from one instance of "java.util.HashMap$HashMapEntry[]", loaded by "<system class loader>"

Keywords
org.bouncycastle.jce.provider.X509CertificateObject
java.util.HashMap$HashMapEntry[]

All comments will be gratefully received开发者_运维知识库


In MAT, I've almost never encountered a "Leak Suspect" that was actually a leak. What you are really looking for are objects that are being retained after a GC sweep that shouldn't be.

For example, suppose I have a Dashboard activity that can launch Activities A and B. I launch the Dashboard, then launch activity A, press the back button, launch activity B, and press the back button.

Using the Eclipse Debug view, you can force a GC collection event via the "Cause GC" button. Now, click the "Dump HPROF file" button and launch MAT. Click on the "Dominator Tree" link.

At this point, I would expect any memory associated with activities A & B to have been collected as garbage unless there was an error in the code. Typically, this is what I would qualify as a 'memory leak' in the app.

This most often occurs due to retained contexts, which can eat a lot of memory since contexts often represent large components (activities, services, etc.).

Anything that looks suspicious in the Dominator Tree can be most easily investigated via the "Path to GC Roots" -> "exclude weak references" option (available via right-click menu). The path2gc roots view is probably the easiest way to find which objects are holding references to objects such that they can't be released.

Once you find unexpected references being retained it can take more digging through the code to understand why . If it has to do with a system/OS component, grepcode is your friend :)


The registering and unregistering of the receiver will lead to memory leaks

As for example if you have registered the receiver with registerReceiver() and in the application it self you try to register it agin without doing unregistering then it will lead you too memory leak issue.

got to know this thing from debugging and bug fixing things.


Based on my experience with creating Android Apps, the OS seems to leave a lot of trash in the memory. However, when the device needs it for something important, it will (almost indiscriminately) take whatever it needs. Even if it overwrites a data in another currently open app.

That aside, there are likely several other things happening in the background that affect your numbers, so I don't beleive we can draw any conclusive information from them. If an application you created is leaking, then there is most likely something you're doing that would cause a memory leak in any other Java based environment as well. An article like: http://www.ibm.com/developerworks/library/j-leaks/ should help with fixing most leaking issues.


If i am experiencing Memory problems with my app i'm using the standalon version of the ddbms tool included in the android development tools.

Have a look at this link: http://android-developers.blogspot.com/2009/02/track-memory-allocations.html

With this tool you can have a look at memory consumption from "the java point of view" so you can see which objects are blocking the most of your memory. This will give you the ability to precisly locate the memory leak you are experiencing and optimizing your code.

The output you have given gives just an overview of All the used memory in your application but not how it is used.


while checking Memory analyzer tool result, mat tool do not promise to find a memory leak but it shows problem or suspect based on its script

MAT tool makes PIE Chart, Dominator Tree, Path 2 GC view based on running application heap analysis

Developer can analyse the memory usage based on above result and enhance their application programming

Very good link to know more about how to remove memory leak is : here

Also : Google IO 2011 video explaining MAT tool , Document, Blog1 and Blog2

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜