开发者

Garbage collector in Android

I have seen many Android answers that suggest calling the garbage collector in some situations.

Is it a good practice to request the garbage collector in Android before doing a memory-hungry operation? If not, should I o开发者_开发技巧nly call it if I get an OutOfMemory error?

Are there other things I should use before resorting to the garbage collector?


For versions prior to 3.0 honeycomb: Yes, do call System.gc().

I tried to create Bitmaps, but was always getting "VM out of memory error". But, when I called System.gc() first, it was OK.

When creating bitmaps, Android often fails with out of memory errors, and does not try to garbage collect first. Hence, call System.gc(), and you have enough memory to create Bitmaps.

If creating Objects, I think System.gc will be called automatically if needed, but not for creating bitmaps. It just fails.

So I recommend manually calling System.gc() before creating bitmaps.


Generally speaking, in the presence of a garbage collector, it is never good practice to manually call the GC. A GC is organized around heuristic algorithms which work best when left to their own devices. Calling the GC manually often decreases performance.

Occasionally, in some relatively rare situations, one may find that a particular GC gets it wrong, and a manual call to the GC may then improves things, performance-wise. This is because it is not really possible to implement a "perfect" GC which will manage memory optimally in all cases. Such situations are hard to predict and depend on many subtle implementation details. The "good practice" is to let the GC run by itself; a manual call to the GC is the exception, which should be envisioned only after an actual performance issue has been duly witnessed.


Out of memory in android application is very common if we not handle the bitmap properly, The solution for the problem would be

if(imageBitmap != null) {
    imageBitmap.recycle();
    imageBitmap = null;
}
System.gc();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 3;
imageBitmap = BitmapFactory.decodeFile(URI, options);
Bitmap  scaledBitmap = Bitmap.createScaledBitmap(imageBitmap, 200, 200, true);
imageView.setImageBitmap(scaledBitmap);

In the above code Have just tried to recycle the bitmap which will allow you to free up the used memory space ,so out of memory may not happen.I have tried it worked for me.

If still facing the problem you can also add these line as well

BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16*1024];
options.inPurgeable = true;

for more information take a look at this link

https://web.archive.org/web/20140514092802/http://voices.yahoo.com/android-virtual-machine-vm-out-memory-error-7342266.html?cat=59


NOTE: Due to the momentary "pause" caused by performing gc, it is not recommended to do this before each bitmap allocation.

Optimum design is:

  1. Free all bitmaps that are no longer needed, by the if / recycle / nullcode shown. (Make a method to help with that.)

  2. System.gc();

  3. Allocate the new bitmaps.


If you get an OutOfMemoryError then it's usually too late to call the garbage collector...

Here is quote from Android Developer:

Most of the time, garbage collection occurs because of tons of small, short-lived objects and some garbage collectors, like generational garbage collectors, can optimize the collection of these objects so that the application does not get interrupted too often. The Android garbage collector is unfortunately not able to perform such optimizations and the creation of short-lived objects in performance critical code paths is thus very costly for your application.

So to my understanding, there is no urgent need to call the gc. It's better to spend more effort in avoiding the unnecessary creation of objects (like creation of objects inside loops)


It seems System.gc() do not work on Art Android 6.0.1 Nexus 5x, So I use Runtime.getRuntime().gc(); instead.


My app manage a lot of images and it died with a OutOfMemoryError. This helped me. In the Manifest.xml Add

<application
....
   android:largeHeap="true"> 


Generally speaking, you should not call GC explicitly with System.gc(). There is even the IO lecture (http://www.youtube.com/watch?v=_CruQY55HOk) where they explain what the GC pauses log mean and in which they also state to never call System.gc() because Dalvik knows better than you when to do so.

On the other hand, as mentioned in the above answers already GC process in Android (like everything else) is sometimes buggy. This means Dalvik GC algorithms are not on par with Hotspot or JRockit JVMs and might get things wrong on some occasions. One of those occasions is when allocating bitmap objects. This is a tricky one because it uses Heap and Non-Heap memory and because one loose instance of bitmap object on the memory-constrained device is enough to give you an OutOfMemory exception. So calling it after you don't need this bitmap any more is generally suggested by many developers and is even considered good practice by some people.

A better practice is using .recycle() on a bitmap as it is what this method is made for, as it marks native memory of the bitmap as safe to delete. Keep in mind that this is very version dependent, meaning it will generally be required on older Android versions (Pre 3.0 I think) but will not be required on later ones. Also, it won't hurt much using it on newer versions either (just don't do this in a loop or something like that). New ART runtime changed a lot here because they introduced a special Heap "partition" for big objects but I think it will not hurt much to do this with ART ether.

Also one very important note about System.gc(). This method is not a command that Dalvik (or JVMs) are obligated to respond to. Consider it more like saying to Virtual machine "Could you please do garbage collection if it's not a hassle".


Best way to avoid OOM during Bitmap creation,

http://developer.android.com/training/displaying-bitmaps/index.html


I would say no, because the Developer docs on RAM usage state:

...
GC_EXPLICIT

An explicit GC, such as when you call gc() (which you should avoid calling and instead trust the GC to run when needed).

...

I've highlighted the relevant part in bold.

Have a look at the YouTube series, Android Performance Patterns - it will show you tips on managing your app's memory usage (such as using Android's ArrayMaps and SparseArrays instead of HashMaps).


Quick note for Xamarin developers.

If you would like to call System.gc() in Xamarin.Android apps you should call Java.Lang.JavaSystem.Gc()


There is no need to call the garbage collector after an OutOfMemoryError.

It's Javadoc clearly states:

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.

So, the garbage collector already tried to free up memory before generating the error but was unsuccessful.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜