does android.media.SoundPool cause memory leak? - android

I found these code may case memory leak on android 2.1
SoundPool soundPool = new SoundPool(10, 7, 0);
...
...
soundPool = null;
every time after the execution, the MAT pluging tells that two String objects of "android:unnamed_thread" are added to the heap of the process. is that an issue?

did you try to run soundPool.release() instead of soundPool = null?

I see two possibilities (there may well be more).
The first (most likely) is true of all Java objects: just because you set the reference to null doesn't automatically mean that the object behind it will be garbage-collected.
If a SoundPool object itself contains a reference to the two thread objects, none of the three will necessarily be GC'ed until space is required (although that depends, of course, on how aggressive your collector is).
The second (less likely) is that Android may be smart enough to cache thread (or even SoundPool) objects in case they need to be used again. They may nave done this as a performance optimisation if object creation is more expensive than object re-cycling.
In that case, they would still have a reference to the objects somewhere in a cache and they wouldn't be considered eligible for garbage collection.

Related

what different between WeakReference and SoftReference

I find the document on this link
It describe as below:
Weak references are useful for mappings that should have their entries removed automatically once they are not referenced any more (from outside). The difference between a SoftReference and a WeakReference is the point of time at which the decision is made to clear and enqueue the reference:
A SoftReference should be cleared and enqueued as late as possible, that is, in case the VM is in danger of running out of memory.
A WeakReference may be cleared and enqueued as soon as is known to be weakly-referenced.
But when I look through the Dalvikvm's source code, found something in dvmCollectGarbageInternal(Heap.cpp L446 Android 4.4) function. It seem two references are
cleared at the same time.
/*
* All strongly-reachable objects have now been marked. Process
* weakly-reachable objects discovered while tracing.
*/
dvmHeapProcessReferences(&gcHeap->softReferences,
spec->doPreserve == false,
&gcHeap->weakReferences,
&gcHeap->finalizerReferences,
&gcHeap->phantomReferences);
Do I miss something?
================================================================================
With #fadden's help, I found the reserve code
if (!marked && ((++counter) & 1))
The dalvikvm reserve the half sofereference every GC procedure, and I copy someone's test code the test
final ArrayList> list = new ArrayList>(
SR_COUNT);
for (int i = 0; i < SR_COUNT; ++i) {
list.add(new SoftReference(new Integer(i)));
}
/* Test */
for (int i = 0; i < 3; ++i) {
System.gc();
try {
Thread.sleep(200);
} catch (final InterruptedException e) {
}
}
/* Check */
int dead = 0;
for (final SoftReference<Integer> ref : list) {
if (ref.get() == null) {
++dead;
}
Log.d(TAG, "dead: " + dead);
}
All the log from logcat is just what I think.
FWIW, the best description of weak/soft/phantom references in Java is in chapter 17 of The Java Programming Language ("Garbage Collection and Memory").
There's no mandated policy for soft reference retention. The VM is allowed to discard all or none during a GC, or anything in between. The only requirement is that the VM is supposed to discard all softly-reachable objects before throwing OOM.
You can continue Dalvik's logic in dvmHeapProcessReferences() in MarkSweep.cpp. Note in particular the call to preserveSomeSoftReferences(), which retains some but not others based on the reference "color". You can read more about colors on the wikipedia GC article.
From Understanding Weak References, by Ethan Nicholas:
https://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html
Weak references
A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself. You create a weak reference like this:
WeakReference weakWidget = new WeakReference(widget);
and then elsewhere in the code you can use weakWidget.get() to get the actual Widget object. Of course the weak reference isn't strong enough to prevent garbage collection, so you may find (if there are no strong references to the widget) that weakWidget.get() suddenly starts returning null.
...
Soft references
A soft reference is exactly like a weak reference, except that it is less eager to throw away the object to which it refers. An object which is only weakly reachable (the strongest references to it are WeakReferences) will be discarded at the next garbage collection cycle, but an object which is softly reachable will generally stick around for a while.
SoftReferences aren't required to behave any differently than WeakReferences, but in practice softly reachable objects are generally retained as long as memory is in plentiful supply. This makes them an excellent foundation for a cache, such as the image cache described above, since you can let the garbage collector worry about both how reachable the objects are (a strongly reachable object will never be removed from the cache) and how badly it needs the memory they are consuming.
And Peter Kessler added in the comments:
The Sun JRE does treat SoftReferences differently from WeakReferences. We attempt to hold on to object referenced by a SoftReference if there isn't pressure on the available memory. One detail: the policy for the "-client" and "-server" JRE's are different: the -client JRE tries to keep your footprint small by preferring to clear SoftReferences rather than expand the heap, whereas the -server JRE tries to keep your performance high by preferring to expand the heap (if possible) rather than clear SoftReferences. One size does not fit all.

Logic behind memory leak in android

Normally in c++ what memory leak is , If we have alloted an object like
Obj c = new Obj();
then if we do
c = b; (example)
we lose the pointer to the object c that's the memory leak.
Question:
But in android Garbage collector collects object when there is no pointers pointing to them. So why there is memory leak even after that ?
Update
All the answers points to holding reference to unused objects is causing memory leak. Thats right. But is that the only cause of memory leak. Holding pointers will be released when activity is finished unless it is static. There are bitmaps and other memory hunger objects , don't they cause any problems in this
In Android/Java memory leak occurs
when you are keeping the reference of an object/instance even after it is no longer required.
when you keep open a file stream, when you are done with it.
Unclosed connections
There are other reasons for memory leak as well, but these are the most common ones.
In garbage collected runtimes, a memory leak means that an object cannot be collected even if it is no longer used. For example, a reference is held to an object but the reference is no longer used for anything.
Casually, the term memory leak is used to refer to situations where these incollectible objects keep on accumulating, increasing the allocated heap size and eventually leading to OOM.
There might be a leak when a Context (an Activity, Service, etc.) is retained by any helper class that would have a reference to it.
Illustration: instead of this:
public class Helper {
private static Context mContext;
public Helper(Context context){
mContext = context;
}
public static void methodDoesSomething(){
...
}
}
Use the context without retaining it by passing it as a parameter:
public class Helper {
public static void methodDoesSomething(Context context){
...
}
}
Because Android will want at some point to destroy an Activity for instance, and an object has a reference to it, The Garbage collector can not remove that Activity thus we have a memory leak.
The answer is partially in your question: Precisely because those references are not freed. Suppose a situation where you have an instance of a class, you've ended working in it but for certain circumstances, the instance keeps there in a state it's not freed. Additionally to Garbage Collector unability to free it, if not controlled, the amount of memory may even increase if it's not handled.
There is one additional thing too. You may have a code that looks correct and well written, but when you instantiate some native libraries, that means you're referencing an hierarchy of classes. If you're not aware of what are you doing, you may precisely handle incorrectly some references and lead to memory leaks. One very popular example is keeping a Context reference into your class. The context instance is never freed and a reason of huge memory leaks.
There are solutions for this, additionally to the obvious (free objects when you're done, etc.). In Java there are SoftReferences, WeakReferences, and other. This objects are containers that tell the Garbage Collector that they have preference on being freed once unused or there are no other references pointing to them. So you're helping the GC to know what should be freed. They're dangerous at a certain point in Android environments, as apps are limited too 16MB of heap, so a WeakReference might be collected too fast. It's necessary to check whether the object still exists.
I think we need to define "Memory Leak" in the first place. Memory leak is something you don't need anymore but it still in the memory and each time a new object is created, a new place will be allocated in the memory. The application will hold more and more memory in time.
private static Drawable background;
#Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
background = getDrawable(R.drawable.large_bitmap);
label.setBackgroundDrawable(background);
setContentView(label);
}
Above example, TextView get Activity as reference, which is a link between
TextView and Activity
now, then there is a static variable
background
which holds the background drawable, static variable will be alive until the application is destroyed or finished. Imagine that you want to destroy the activity, when you destroy static variable will still hold a link to activity, because of that garbage collector won't be able to collect it.
You can have a look at here about more.

Java android optimization. Non-static or static method?

I have a static class with a method in it that I run a few hundred times. Currently, everytime the method is run, it creates two different stack objects. If I were to make that class non-static so I can create the two stacks on construction and then reuse them by clearing them, would it be quicker? I guess the answer depends on creating a new stack object vs clearing an existing one (which is likely empty anyway) and if the performance gain (if any) from clearing it instead is greater than the performance loss from having a non-static method.
I've tried profiling the two and it never seems to work, but that's a different question.
It depends on how you use static variables and method in your code.
Instance variables and objects are stored on the heap.
Local variables are stored on the stack.
Static variables are stored in a permanent area on heap. The garbage collector works by marking and sweeping objects. Static variables cannot be elected for garbage collection while the class is loaded. They can be collected when the respective class loader (that was responsible for loading this class) is itself collected for garbage.
If i have a value to be passed to another activity i would use intents instead of static variables.
In a custom list adapter we use a static viewholder. So using static variables or methods depends on different situation.
You can analyze memory usage by objects using a tool called MAT Analyzer. The video in the below talks about memory management and how to detect and solve memory leaks
http://www.youtube.com/watch?v=_CruQY55HOk.
MemoryInfo mi = new MemoryInfo();// current memory usage
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem / 1048576L;
http://developer.android.com/training/articles/perf-tips.html. Have a look at this link for performance tips especially the topic under Prefer Static Over Virtual.
Memory availabilty is one of the criteria's to be considered using static variables and methods for performance and avoiding memory leaks.
This is really a question about trying to reuse objects. You can reuse objects in a static method too if you declare a static member. Separately: yes it's probably better to design this without static anything.
In any event, the upside to reuse is avoiding object creation. You still pay some cost of "clearing" the object's state. Or else, you risk memory leaks in the case of something like a Stack.
There is an ongoing maintenance issue: you add new state to the object, and, did you remember to update the method that clears it?
You also need to now synchronize access to this method or otherwise prevent two threads from using it at once. That could introduce a bottleneck as threads can't execute the method concurrently.
You also always pay the memory cost of this object living in memory for the entire runtime.
In the olden days, people would create object pool abstractions to avoid recreating objects. This has its own complexity and runtime overhead, and are generally well out of favor, since the cost of creating an object and GCing it is so relatively small now.
Trying to reuse objects solely for performance is rarely a performance win. It would have to be in a tight loop and not suffer from several possible problems above to be worth it.

Guaranteeing object reuse while copying an object in Java [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
In the following code we rotate a complex number by some angle in a loop and then confirm that the resulting number is identical to the one we started with.
public class Complex {
private float r, i;
...
public Complex(Complex other) {
r = other.r;
i = other.i;
}
}
Complex z1 = new Complex(..);
Complex z1_save = new Complex(z1);
Complex z2 = new Complex();
Complex k = new Complex();
k.set_to_first_root_of_unity(8);
int n = 64;
while(n-- != 0) {
z1.multiply(k, z2);
z1 = new Complex(z2); // Line Y
}
Assert.assertEquals(true, z1.equals(z1_save));
Is there a way in Java to write Line Y using the constructor public Complex(Complex other) rather than clone(), and be certain that 64 objects will not be garbage collected?
Update: It seems it is impossible to ask this question in a simplified manner without referring to the context—that of an interactive application. The best answer to the present question so far (assylias's) is that one should not worry about object creation and garbage collection 90% of the time. During redraw, it is necessary to worry about it 100% of the time. I have now restated the question here.
I am worried about the inefficiency of the GC running 64 times unnecessarily.
That is an unnecessary worry. If your objects are in the young generation (which they will considering their scope) GC will be free (as in 0 cost).
When the GC runs on the young generation, it only goes through live objects (objects that are eligible for GC are not visited), so the GC time is a function of the live objects only.
The story is different for the old generation, but your local objects won't reach that stage.
Reference - Brian Goetz, emphasis mine:
What about deallocation?
But allocation is only half of memory management -- deallocation is the other half. It turns out that for most objects, the direct garbage collection cost is -- zero. This is because a copying collector does not need to visit or copy dead objects, only live ones. So objects that become garbage shortly after allocation contribute no workload to the collection cycle.
?It turns out that the vast majority of objects in typical object-oriented programs (between 92 and 98 percent according to various studies) "die young," which means they become garbage shortly after they are allocated, often before the next garbage collection. (This property is called the generational hypothesis and has been empirically tested and found to be true for many object-oriented languages.) Therefore, not only is allocation fast, but for most objects, deallocation is free.
Executing constructor 64 times for an object with ten (or so) fields is not a big deal even for a device like a cell phone.
It is not clear what your task is.
If you are really concerned about calling constructor many times and creating too many identical object, you may try to use the Flightweight pattern.
Your question (and comments) are a bit confused ... but that might just be a problem with your written English skills. So I'm just assuming I understand what you meant to say. I'm also assuming that your example "works" ... which it currently doesn't.
The short answer is that you can reduce object churn (i.e. creation and release of "temporary" objects) by making your Complex object mutable. Typically you do this by adding setter operations that allow you to change the state of the object. But that has the effect of making your Complex class more difficult to use correctly. For example:
public static final ZERO = new Complex(0, 0);
// somewhere else
Complex counter = ZERO;
while (counter.lessThan(10)) {
// ....
counter.setRealPart(counter.getRealPart() + 1); // Ooops!!
}
... and lots more bugs like that.
Then there is the question of whether this will actually reduce garbage collection overheads, and by how much.
As #assylias points out, temporary objects that are created and then reclaimed in the next GC cycle have very low cost. The objects that are expensive are the ones that DON'T become garbage. And it is quite possible that for a normal program running in a normal environment, it is actually more efficient overall to create temporary objects.
Then there is the issue that the latest HotSpot JVMs can do something known as "escape analysis", which (if it works) can determine that a given temporary object will never be visible outside of its creation scope, and therefore doesn't need to be allocated in the heap at all. When that optimization can be applied, the "object churn" concern is mooted.
However, running the GC can be bad for "real time" performance; e.g. in games programming, where the user will notice if the game freezes for a fraction of a second. In cases like that, it is worth considering "tuning" your code to reduce object churn. But there are other possible approaches too ... like using a low-pause garbage collector ... if one is available for your platform.
#assylias's comment makes another important. Beware of premature optimization. Your intuition on the usage of your Complex object ... and the resulting object churn ... could be very wrong. All things being equal, it is best to delay optimization effort until you have profiled the application and determined that:
it needs to be tuned, and
the profiling evidence points to the Complex class being a significant performance bottleneck.
There's no reason to pay attention to garbage collection at all, unless:
users (maybe you) perceive performance issues with the application; and
profiling the application demonstrates that garbage collection is the source of the perceived performance issues.
Lacking both of these conditions: ignore garbage collection.
This is true of performance tuning in Java in general. Don't do it unless you've proven there's a real reason for it.
If you want to be efficient w.r.t GC, minimize your use of new.
So, in your example, you could re-use the variable in "Line Y", and simply set the fields with the new value. Something like:
while(n-- != 0) {
z1.multiply(k, z2);
z1.setValue(z2); // Line Y
}
where z1.setValue(X) sets the state of the object in the same fashion that the constructor new Complex(x) does.
EDIT: Why is this getting down voted? I stand by the statement above about reducing the cost of GC by minimizing the use of new. Yes, I agree in most contexts GC is not a problem - but if your code does call GC frequently, perhaps because your code spends a lot of time in a loop (say a CPU heavy algorithm), then you may well want to reuse objects.

DDMS Heap - 1-byte array(byte[], boolean[])

I experience some memory leaks in my android application. I've already used MAT to analyze the memory usage. But I have one question from the DDMS perspectiv in Eclipse, what does 1-byte array[byte[], boolean[]) mean?
Is this specific for my application? You can see that this is the big memory leak issue, this always increases in size, and the rest will increase and decrease randomly. My guess is that the GC doesn't catch this type. Can anybody explain why this happen, with this little information?
One byte array is the designation for any data structure that is organized as a single byte array. In you case and with that size, I would bet in a Bitmap or a Drawble.
Most common reasons for memory leaks are static object not properly managed and holding references to:
Context
View (which holds reference to context (and possibly also to bitmap)
Thread (which are not easly collected by GC)
Handler (which holds reference to context)
Most of them can be solved ensuring that you set the object to null when it's no long required.
Regards.
A byte and a boolean are each 1 byte. If you have an array of those you have a "1-byte array".
A ByteBuffer for example should internally hold one of those.
You have a total of 614 of them where the smallest one be a byte[24] (or boolean[24]), the largest one is 3MB. All of them together use 104MB.
The GC will get rid of them if they are no longer referenced.
For example when you put
private static byte myArray[] = new byte[3 * 1024 * 1024];
in one of your classes and never set it back to null (myArray = null) then this one can't be garbage collected because another Object has a reference to it. The object would be the class itself (as in String.class). The class object can't be garbage collected since classes are never unloaded. (they are referenced by their ClassLoader which could itself be referenced / loaded by another ClassLoader and you can't create Objects & use classes without them - they need to stay and they need to keep a reference to their classes)
It's usually not that simple but often start with static somewhere.
Within MAT (after you force GC) look at the reference chain for the objects that are no longer intended to stay alive and identify the one Object that holds the reference. Set that one to null in your code and your leak is gone. Explained in more detail here:
http://android-developers.blogspot.de/2011/03/memory-analysis-for-android.html
I ran to this problem tonight and almost I checked every bit of code but I couldn't find anything.
What I did was starting the app from intelij and then pressing home button and open the app again. Every time the app heap was doubled.
Finally I discover when I launch the app from ADB and press the home button and open the app again it doesn't bring back the old activity, it just start a new one. When I pressed finish it starts to cycle through all of them. It's like they are treated as two different intent. So I put android:launchMode="singleTop" on the main activity in manifest and it resolved the problem.
Although it's not the main cause of this problem but if you encountered this check this out before anything. It wasted three or four hours for me.

Categories

Resources