Garbage Collector in Android

Garbage collector in Android

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.

Garbage Collection in android (Done manually)

it isn't good programming habit to call forcefully garbage collector (System.gc()) at the end of each activity

Because it is useless,only DVM decide when it should be call although you called it...

Garbage Collector not freeing trash memory as it should in an Android application

Garbage collection is complicated, and different platforms implement it differently. Indeed, different versions of the same platform implement garbage collection differently. (And more ... )

A typical modern collector is based on the observation that most objects die young; i.e. they become unreachable soon after they are created. The heap is then divided into two or more "spaces"; e.g. a "young" space and an "old" space.

  • The "young" space is where new objects are created, and it is collected frequently. The "young" space tends to be smaller, and a "young" collection happens quickly.
  • The "old" space is where long-lived objects end up, and it is collected infrequently. On "old" space collection tends to be more expensive. (For various reasons.)
  • Object that survive a number of GC cycles in the "new" space get "tenured"; i.e they are moved to the "old" space.
  • Occasionally we may find that we need to collect the new and old spaces at the same time. This is called a full collection. A full GC is the most expensive, and typically "stops the world" for a relatively long time.

(There are all sorts of other clever and complex things ... which I won't go into.)


Your question is why doesn't the space usage drop significantly until you call System.gc().

The answer is basically that this is the efficient way to do things.

The real goal of collection is not to free as much memory all of the time. Rather, the goal is to ensure that there is enough free memory when it is needed, and to do this either with minimum CPU overheads or a minimum of GC pauses.

So in normal operation, the GC will behave as above: do frequent "new" space collections and less frequent "old" space collections. And the collections
will run "as required".

But when you call System.gc() the JVM will typically try to get back as much memory as possible. That means it does a "full gc".

Now I think you said it takes a couple of System.gc() calls to make a real difference, that could be related to use of finalize methods or Reference objects or similar. It turns out that finalizable objects and Reference are processed after the main GC has finished by a background thread. The objects are only actually in a state where they can be collected and deleted after that. So another GC is needed to finally get rid of them.

Finally, there is the issue of the overall heap size. Most VMs request memory from the host operating system when the heap is too small, but are reluctant to give it back. The Oracle collectors note the free space ratio at the end of successive "full" collections. They only reduce the overall size of the heap if the free space ratio is "too high" after a number of GC cycles. There are a number of reasons that the Oracle GCs take this approach:

  1. Typical modern GCs work most efficiently when the ratio of garbage to non-garbage objects is high. So keeping the heap large aids efficiency.

  2. There is a good chance that the application's memory requirement will grow again. But the GC needs to run to detect that.

  3. A JVM repeatedly giving memory back to the OS and and re-requesting it is potentially disruptive for the OS virtual memory algorithms.

  4. It is problematic if the OS is short of memory resources; e.g. JVM: "I don't need this memory. Have it back", OS: "Thanks", JVM: "Oh ... I need it again!", OS: "Nope", JVM: "OOME".

Assuming that the Android collector works the same way, that is another explanation for why you had to run System.gc() multiple times to get the heap size to shrink.


And before you start adding System.gc() calls to your code, read Why is it bad practice to call System.gc()?.

Android Garbage collector Runs on Main Thread?

If you have strong reference to an object then that object is not eligible for GC.

There is no way strong referenced object will get disposed in code between null check and next line... or any other line as long as you can access that object reference. Only if you set that object reference to null, or you assign another object to that reference, previous object can be garbage collected if there are no other references pointing to it.

On the other hand, when you are dealing with weak references (of any kind) first you have to take strong reference out of weak reference wrapper and then you can safely use that strong reference further on (after you check it is not null, of course). If you don't take strong reference, object in weak wrapper can vanish at any time.

Wrong usage - object can be collected between null check and getName call

if(item.get()!=null)
item.get().getName();

Correct usage - taking strong reference for further processing

Object object = item.get();
if(object!=null)
object.getName();

Why Android VM not use G1 Garbage Collector

Your question is based on a number of false premises:

  1. Android does NOT use the OpenJDK CMS collector. It has its own garbage collector.

  2. The page that you linked to does NOT mention OpenJDK or CMS:

    • It does say that the Android GC is generational, but many, many collectors are generational.
    • It does NOT say that the Android collector is concurrent, which is one of the important characteristics of CMS and G1.
  3. Android is NOT based on the OpenJDK codebase. Therefore, the OpenJDK garbage collectors would not work in Android without (probably) a complete rewrite.

  4. OpenJDK is covered by GPLv2 with the classpath extension, so the source code would technically be available to be ported. However, the copyright remains with Oracle. I cannot imagine Google wanting to incorporate any Oracle copyright code into the Android codebase. (Especially given Oracle's unpleasant history of using litigation to gain a competitive advantage.)

  5. The platform requirements for Android and OpenJDK are significantly different. For example, OpenJDK is optimized for running services rather than apps. The characteristics that make G1 attractive on a typical enterprise server are not necessarily a good match for an "app" running on someone's mobile phone, where (for example) there is less RAM and fewer cores, and power consumption / battery life are critical concerns.

In short, it doesn't make much sense for Android to support the G1 collector. And it is unlikely that it will ever happen.

How to solve frequent garbage collection in android?

After doing some R&D and doing work on suggestions, Our app is 50-70% (Depending on RAM on different devices) performing better as per before.

I raised some points for the issue, I configure that:

  • Is this caused due to any module or library??

Some modules make our APK size a little bit large at the time of debugging. So, if we apply progaurd or use bundle then our app APK will become less in size and will also take less RAM at that time.

  • Using too many images in nested recycler views like Playstore.

Use the famous libraries for image loadings like glide or Picasso,
we need bitmap pooling for images which we are using again and again.
This will help us to avoid more and more bitmaps for the same image URLs

Reference: Here is the good guidance, how to optimize recycler view

  • Using AutoScrollViewPager with 1.5 secs of delay

Here is the major issue that comes, after using the app for 3-5 mins, GC calls so frequently, and that is due to ViewPager.setCurrentItem(). For the whole application where we are using ViewPager and changing pages GC calls.

In AutoScrollViewPager there is a delay with 1.5 secs and then ViewPager AutoScrolls, then GC calls. That's why there are too many GCs in the android profiler after every 2 secs.

So, we removed the code for AutoScrolling, performance is better from the last scenario.

Some other optimizations are:

  • Replaces multiple instances to singleton instances.
  • Removed all Leaks from the application.

Reference: Here is about Memory Leaks in Android

Any suggestions for this issue will be helpful for all.
Thank you



Related Topics



Leave a reply



Submit