Tofeeq Ahmad
Tofeeq Ahmad

Reputation: 11975

Garbage Collection in android (Done manually)

I have a strange doubts. I know garbage collector has its own limitation. and if allocation is bad then it can cause a problem for application to respond in unusual way.

So my question is that is it good programming habit to call forcefully garbage collector (System.gc()) at the end of each activity?

Update

Every one is saying that calling system.gc() not beneficial at all.Then i am wondering why its present here.DVM will decide when to run garbage collector.Then what is need of that method?

Update 2

Thanks community to help me out. But honestly i got knowledge about Garbage collection real Beauvoir from this link Java Performance Optimization

Upvotes: 10

Views: 21233

Answers (8)

Stephen C
Stephen C

Reputation: 718886

It is possible to ask the Android JVM to run the garbage collector by calling System.gc(). As the documentation states:

Calling the gc() method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

Emphasis added!

Some care is needed in interpreting "best effort" in the final sentence:

  • The "best effort" might be to ignore the "suggestion" entirely. Some JVMs have a configuration option to totally ignore System.gc() calls.

  • The "best effort" may or may not amount to a full garbage collection. That is an implementation detail.

But the bottom line is that you cannot force the GC to run.


Calling System.gc() is generally a bad idea. It makes your application inefficient, and it may introduce unwanted and unnecessary GC pauses.

The inefficiency issue comes down to the way that modern garbage collectors behave. A garbage collector's work has two parts1:

  1. Finding the objects that are reachable.
  2. Dealing with the objects that are not reachable.

The first part involves traversing reference chains and and marking the graph of objects starting at the GC roots. This work is proportional to the number of reachable objects.

The second part can be handled in a couple of ways, but it will typically be proportional to the size of the reachable objects.

Thus the overall cost of a GC run (in CPU time) depends mostly in the amount of non-garbage. But the benefit of the work performed is the amount of space that you managed to reclaim.

To maximize efficiency, you need to run the GC when the benefit of running the GC is at its highest; i.e. when the heap is close to full. But the problem is that if you call System.gc() you may be requesting a garbage collection when there is lots of free space.


Every one is saying that calling system.gc() not beneficial at all. Then I am wondering why its present here. DVM will decide when to run garbage collector. Then what is need of that method?

It is there for largely historical reasons. The method was present in the System class in Java 1.0. Removing it now would break a lot of legacy code. As for why gc() was included in the first place, the decision was made a long, long time ago, and we were not "in the room" when it was made. My guess is that the decision makers (in ~1995):

  • were a bit too optimistic about how GC technology would develop,
  • didn't anticipate that naive programmers would try to use gc() calls to solve memory leaks and other bugs, and / or
  • were simply too rushed to think too hard about it.

There are also a couple of scenarios where calling System.gc() is beneficial. One such scenario is when your application is about to start a "phase" where unscheduled GC pauses are going to give a particularly bad user experience. By running System.gc() you can take the "performance hit" at a point in time where it matters less; e.g. during a user initiated pause or while switching levels in a game.

But I don't think the above scenario corresponds to your "at the end of every activity".


The final thing to note is that calling System.gc() manually does not prevent normal OOMEs. A normal OOME is typically thrown then the JVM decides there is not enough free heap space to continue. This decision is made immediately after running a (full) GC. Running System.gc() manually won't make any difference to the decision making.

Furthermore, calling System.gc() will not cure normal2 memory leaks. If your application has a memory leak, you actually have a situation where a bunch of objects are reachable when they shouldn't be. But since they are reachable, the GC won't delete them.

The cure for OOMEs is one or more of the following:

  1. Find the memory leaks and fix them. There are tools to help you do this.
  2. Modify the application to use memory more efficiently; e.g. don't keep so much data in memory, or represent it in a more compact form.
  3. Increase the application's heap size.

1 - This is a simplification, but the full story is way to complicated for this posting. I recommend you buy an read an up-to-date book on Garbage Collection of you want (or need) a deeper understanding.
2 - There are cases involving non-heap memory where manually running the GC might help as a band-aid for certain kinds of OOME. But a better solution is to find a better way to reduce non-heap memory usage and/or free up non-heap resources in a more timely fashion.

Upvotes: 1

Farbod Salamat-Zadeh
Farbod Salamat-Zadeh

Reputation: 20080

Calling GC manually is a bad coding habit...

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 most important and relevant part here in bold.

Upvotes: 0

stevebot
stevebot

Reputation: 24005

I really think it depends on your situation.

Because the heap is generational, the GC may not get rid of certain large objects or bitmaps on its first pass, and its heuristics may not indicate that additional garbage collection is necessary, but there are definitely scenarios where the heuristic could be wrong, and we as the developers have knowledge of a pattern, or can predict usage that the GC cannot, and therefore calling system.gc() will benefit us.

I have seen this before in specific scenarios such as dealing with map tiling or other graphic intensive behaviors, where the native GC in Android (even on 3.0+ devices), doesn't get it right, resulting in Out of Memory errors. However, by adding a few GC calls, the Out of Memory errors are prevented, and the system continues to process albeit at a slower rate (due to garbage collection). In graphic intensive operations, this usually is that state desired (a little lag) over the application crashing because it cannot load additional resources into memory.

My only explanation for why this happens in certain scenarios appears to be timing. If user operations are slow, then the native Android GC seems to do great. However, if your user is scrolling fast, or zooming quickly, this is where I have seen the Android GC lag behind, and a few well thought out System.gc() have resulted in my applications not crashing.

Upvotes: 5

Yusuf X
Yusuf X

Reputation: 14633

System.gc(), which the VM sometimes ignores at whim, is mostly useful in two cases:

  1. you're gobbling up memory like there's no tomorrow (usually with bitmaps).
  2. you suspect a memory leak (such as accidentally holding onto an old Context), and want to put the VM memory in a quiescent state to see if the memory usage is creeping up, for debugging.

Under nominal circumstances, one should not use it.

Upvotes: 4

Danny Remington - OMS
Danny Remington - OMS

Reputation: 5502

I tried putting System.gc() on the line before the lines where I created my bitmap in my Android app. The garbage collector freed up several megabytes in some cases and put and end to my OutOfMemoryError conditions. It did not interfere with the normal garbage collection one bit but it did make my app run faster.

Upvotes: 2

Last Warrior
Last Warrior

Reputation: 1307

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...

Upvotes: 13

ngesh
ngesh

Reputation: 13501

calling System.gc(), doesn't do any harm. but you cant be sure that it will be of some use. because you ask the DVM to do garbage collection, but can't command it... Its dependent totally on DVM. It calls when memory is running out or may be at any time..

Upvotes: 2

Dave Newton
Dave Newton

Reputation: 160191

No; if the system needs memory, it will call GC on its own.

Any memory used by an instance, that isn't referenced anywhere else, will become eligible for GC when the instance goes away.

Memory used by the instance itself, if no longer referenced, is also eligible for GC. You can do a code review or profiling to see if you're holding on to memory unnecessarily, but that's a different issue.

Upvotes: 1

Related Questions