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
If you suspect you are running into a temporal leak, a good way to check is to use Android Studio's memory profiler. Once you start a session within the profiler, take the steps to reproduce the leak, but wait for a longer period of time before dumping the heap and inspecting. The leak may be gone after the extra time.
Once you run the application LeakCanary will automatically be installed on your device. By opening the LeakCanary, you will see a detailed view of the leaks. The details screen shows a trace of the memory leak that starts from the garbage collector root to the objects passing the leaked reference.
Physical or permanent damage does not happen from memory leaks. Memory leaks are strictly a software issue, causing performance to slow down among applications within a given system.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With