regarding garbage collection.Why do we need to call System.gc();? - java

Garbage collection is called automatically when an object is refered to is no longer available to any variable. But I like know why do we call explicitly using System.gc() when garbage collection is called automatically.When do we call System.gc();

You don't. As you say, garbage collection is automatic. System.gc() doesn't even force a garbage collection; it's simply a hint to the JVM that "now may be a good time to clean up a bit"
In general, trying to force the garbage collector to do what you want with System.gc() is a hack applied by people who think they know better than they actually do, or as an (attempted) workaround for broken code.
I've been writing Java for years and I've yet to see a situation where calling System.gc was really the right thing to do (in anything I've written)

We don't.
We just don't.
Perhaps my experience is limited, but I have not once found it necessary to call System.gc().
I will quote Brian Goetz on the performance aspect (if you haven't heard of him, look him up -- and read the rest of this article, too):
A third category where developers often mistakenly think they are helping the garbage collector is the use of System.gc(), which triggers a garbage collection (actually, it merely suggests that this might be a good time for a garbage collection). Unfortunately, System.gc() triggers a full collection, which includes tracing all live objects in the heap and sweeping and compacting the old generation. This can be a lot of work.
In general, it is better to let the system decide when it needs to collect the heap, and whether or not to do a full collection.

You don't need it. Think of it as a diagnostic tool, like being able to write to a debug console.
For example, imagine that if you were doing benchmarking, you would want to tell the GC to collect garbage after each benchmark run.

You do need it. It is very useful no matter what these other people say.
A usage example:
Say that you have just finished a long background task that has used a lot of memory. None of those objects are going to be used again. Since the task took a long time the user isn't going to care about another 5-10 seconds. This is a good time to garbage collect.
If you don't GC at that point, it is going to happen later. Probably during interactive use of the program at which point the user experience gets choppy.

Related

does java Java has manual garbage collection?

Ok today I was in an interview and I have been coding Java for years. The interview said "Java garbage collection is a tricky one I had few friends who had struggled figuring out. How are you doing on that?". Was she trying to trick me? or is my entire life a lie and java does not have automatic garbage collection?
Because as far as i know java has automatic garbage collection and you can call System.gc() to collect some resources but this does not force the object to get destroyed. It is still decided by JVM.
Am I wrong?
Just because the garbage collection is automatic doesn't means you can just completely ignore the implications of object allocation and cleanup and how the GC works.
For many applications, especially simple ones, it will be fine to just let the GC do it's thing. Although even then you have to make sure you are not holding onto references longer than needed.
As your application becomes bigger and more complicated, especially if you are using any multi-threading, the impact the GC poses becomes more of a concern and it becomes more important to understand how everything is working in your code and what the GC is doing.
GC is automatic, yes.
But some practices related to GC may be subtle and so should be known and understood to avoid memory leak or undesirable behavior.
For example :finalize()
is called by the garbage collector on an object when garbage collection
determines that there are no more references to the object
according to the javadoc but in reality it could never be called.
Other example : GC collects remove the objects that are no referenced any longer but you could have a "heavy" object that is not any longer required but still referenced by a referenced object. So the heavy would not be elligible to be collected.
Using monitoring tools as JVisualVM shows sometimes some surprises and I say : Ah, this big object is still referenced here...

why it took several times of gc for jvm to find the weakreference?

I konw the GC in jvm will collect the object once it found the object is weak referenced, but some people say that it maybe tooks several times of gc for the jvm to find the weak referenced objects, I don't really understand it, is anyone can explain it, or tell me is it true? thanks!
Garbage collection for all practical purposes is indeterministic. You simply can't predict when it'll clean something, if it'll cause your app to briefly pause etc. Most of the time it behaves well. You should never rely on underlying gc actions or finalizers.
Yes, it takes a while before object will be destroyed. I do not know of anything wrong with Java WeakReference or its impact on performance.
May result in additional Garbage Collection
You cannot know when the cycle is performed. Garbage Collector working in cycles in own background thread.
WeakReferences managing depends on implementation of JRE (like everything), see also Cost of using weak references in Java
There are no way to destroy object manually in Java and other advanced languages like C# for example. Garbage collector do that work. In cycles finalize and destroy objects without reference (i.e. strong reference). Weak references does not prevent the object to be collected by Garbage Collector. Difference between reference type are explained here on StackOverflow.
There is no way to trigger collection cycle. You can poke Garbage Collector by System.gc() but it does not cause immediate execution and "take several times".

What conditions would prevent the JVM from running a FULL Garbage Collection?

What conditions would prevent the JVM from running a FULL Garbage Collection when the CPU is at 5% to 8% load?
I am seeing a constant shallow GC cycle, but not able to tune the JVM to want to run FULL GC.
Where can I go to find the conditions that the JVM says "I am too busy to run".
When I was studying for my SCJP certification a lot of emphasis was made on
"You can not do anything to force the
GC to run at any given time, you can
just give hints to it"
The whole idea of having an automatic GC is precisely not having to worry about how or when it runs to clean up free memory for you. So, there is no way to actually change when or how GC does actually run... you would have to re-implement one JVM to do what you want.
There are just so many factors involved in this, there may be other, more elegant solutions for this.
It depends entirely on the garbage collector algorithm that you're using in your particular JDK. About all you can guarantee about garbage collection is that if the JVM throws an OutOfMemoryError, the garbage collector made its best effort to collect every unreachable/weakly reachable object. Even System.gc() doesn't guarantee anything, a no-op is a completely legal implementation.
Hence in that light I don't know if your question has any weight. If you truly believe that you need to tweak the garbage collector, it would help if you posted the problems you're seeing, and the profiling data that leads to believe that poor GC performance is the problem.
Outside of this, the garbage collector should be treated like a black box. The logic behind its implementation is surprisingly complex, and there's a very good chance it knows better than you what it ought to be doing at any given time. 99 times out of 100, trying to force the garbage collector to behave in a particular way will lower performance, not increase it.
It's not that it's to busy to run, but it does simply not need extra memory.

Garbage collector and finalize() method

You people may think that within 15-20 minutes i have asked 4-5 questions on the same topic, so I may need a tutorial on this. But i am getting these questions by reading about GC.
So my question is GC will call a finalize() method on an instance only once of its life cycle even though if the same object is made uneligible to garbage collect in its finalize() method. So i wanted to know that how GC will come to know that it has executed its finalize() method once before while collecting it for the second time
Honestly, your life will be much better if you forget that finalizers exist. I've been coding Java for years and never had a reason to use a finalizer.
They're slow, not well defined (sometimes they'll never run!), and generally a PITA.
Do something along the lines of the Closeable interface instead if you are managing external resources, and use try{} finally{} blocks to clean up. Otherwise, try as much as you can to trust the language to clean up memory after itself.
Implementation dependent. Presumably the VM either has a secret bit on every object, or has a table containing objects that have already been "finalized". If I had to guess, I'd say the latter since presumably the set of already finalized objects that are still hanging around is expected to be small, so having a bit on every object in the system seems a bit wasteful.
Ah you again :)
Note that on the subject of finalizers, if you really FORCE a GC using JVMTI's ForceGargabeCollection, it is specifically stated that:
"This function does not cause finalizers to be run."
Once again, you probably do not really want to do that, but then if you have 2K+ rep and 5 questions about the GC is think that it's interesting to keep repeating that using JVMTI's ForceGarbageCollection you can really FORCE a GC.
Authoritative info as to how to force a GC:
http://java.sun.com/javase/6/docs/platform/jvmti/jvmti.html#ForceGarbageCollection

Why do you not explicitly call finalize() or start the garbage collector?

After reading this question, I was reminded of when I was taught Java and told never to call finalize() or run the garbage collector because "it's a big black box that you never need to worry about". Can someone boil the reasoning for this down to a few sentences? I'm sure I could read a technical report from Sun on this matter, but I think a nice, short, simple answer would satisfy my curiosity.
The short answer: Java garbage collection is a very finely tuned tool. System.gc() is a sledge-hammer.
Java's heap is divided into different generations, each of which is collected using a different strategy. If you attach a profiler to a healthy app, you'll see that it very rarely has to run the most expensive kinds of collections because most objects are caught by the faster copying collector in the young generation.
Calling System.gc() directly, while technically not guaranteed to do anything, in practice will trigger an expensive, stop-the-world full heap collection. This is almost always the wrong thing to do. You think you're saving resources, but you're actually wasting them for no good reason, forcing Java to recheck all your live objects “just in case”.
If you are having problems with GC pauses during critical moments, you're better off configuring the JVM to use the concurrent mark/sweep collector, which was designed specifically to minimise time spent paused, than trying to take a sledgehammer to the problem and just breaking it further.
The Sun document you were thinking of is here: Java SE 6 HotSpot™ Virtual Machine Garbage Collection Tuning
(Another thing you might not know: implementing a finalize() method on your object makes garbage collection slower. Firstly, it will take two GC runs to collect the object: one to run finalize() and the next to ensure that the object wasn't resurrected during finalization. Secondly, objects with finalize() methods have to be treated as special cases by the GC because they have to be collected individually, they can't just be thrown away in bulk.)
Don't bother with finalizers.
Switch to incremental garbage collection.
If you want to help the garbage collector, null off references to objects you no longer need. Less path to follow= more explicitly garbage.
Don't forget that (non-static) inner class instances keep references to their parent class instance. So an inner class thread keeps a lot more baggage than you might expect.
In a very related vein, if you're using serialization, and you've serialized temporary objects, you're going to need to clear the serialization caches, by calling ObjectOutputStream.reset() or your process will leak memory and eventually die.
Downside is that non-transient objects are going to get re-serialized.
Serializing temporary result objects can be a bit more messy than you might think!
Consider using soft references. If you don't know what soft references are, have a read of the javadoc for java.lang.ref.SoftReference
Steer clear of Phantom references and Weak references unless you really get excitable.
Finally, if you really can't tolerate the GC use Realtime Java.
No, I'm not joking.
The reference implementation is free to download and Peter Dibbles book from SUN is really good reading.
As far as finalizers go:
They are virtually useless. They aren't guaranteed to be called in a timely fashion, or indeed, at all (if the GC never runs, neither will any finalizers). This means you generally shouldn't rely on them.
Finalizers are not guaranteed to be idempotent. The garbage collector takes great care to guarantee that it will never call finalize() more than once on the same object. With well-written objects, it won't matter, but with poorly written objects, calling finalize multiple times can cause problems (e.g. double release of a native resource ... crash).
Every object that has a finalize() method should also provide a close() (or similar) method. This is the function you should be calling. e.g., FileInputStream.close(). There's no reason to be calling finalize() when you have a more appropriate method that is intended to be called by you.
Assuming finalizers are similar to their .NET namesake then you only really need to call these when you have resources such as file handles that can leak. Most of the time your objects don't have these references so they don't need to be called.
It's bad to try to collect the garbage because it's not really your garbage. You have told the VM to allocate some memory when you created objects, and the garbage collector is hiding information about those objects. Internally the GC is performing optimisations on the memory allocations it makes. When you manually try to collect the garbage you have no knowledge about what the GC wants to hold onto and get rid of, you are just forcing it's hand. As a result you mess up internal calculations.
If you knew more about what the GC was holding internally then you might be able to make more informed decisions, but then you've missed the benefits of GC.
The real problem with closing OS handles in finalize is that the finalize are executed in no guaranteed order. But if you have handles to the things that block (think e.g. sockets) potentially your code can get into deadlock situation (not trivial at all).
So I'm for explicitly closing handles in a predictable orderly manner. Basically code for dealing with resources should follow the pattern:
SomeStream s = null;
...
try{
s = openStream();
....
s.io();
...
} finally {
if (s != null) {
s.close();
s = null;
}
}
It gets even more complicated if you write your own classes that work via JNI and open handles. You need to make sure handles are closed (released) and that it will happen only once. Frequently overlooked OS handle in Desktop J2SE is Graphics[2D]. Even BufferedImage.getGrpahics() can potentially return you the handle that points into a video driver (actually holding the resource on GPU). If you won't release it yourself and leave it garbage collector to do the work - you may find strange OutOfMemory and alike situation when you ran out of video card mapped bitmaps but still have plenty of memory. In my experience it happens rather frequently in tight loops working with graphics objects (extracting thumbnails, scaling, sharpening you name it).
Basically GC does not take care of programmers responsibility of correct resource management. It only takes care of memory and nothing else. The Stream.finalize calling close() IMHO would be better implemented throwing exception new RuntimeError("garbage collecting the stream that is still open"). It will save hours and days of debugging and cleaning code after the sloppy amateurs left the ends lose.
Happy coding.
Peace.
The GC does a lot of optimization on when to properly finalize things.
So unless you're familiar with how the GC actually works and how it tags generations, manually calling finalize or start GC'ing will probably hurt performance than help.
Avoid finalizers. There is no guarantee that they will be called in a timely fashion. It could take quite a long time before the Memory Management system (i.e., the garbage collector) decides to collect an object with a finalizer.
Many people use finalizers to do things like close socket connections or delete temporary files. By doing so you make your application behaviour unpredictable and tied to when the JVM is going to GC your object. This can lead to "out of memory" scenarios, not due to the Java Heap being exhausted, but rather due to the system running out of handles for a particular resource.
One other thing to keep in mind is that introducing the calls to System.gc() or such hammers may show good results in your environment, but they won't necessarily translate to other systems. Not everyone runs the same JVM, there are many, SUN, IBM J9, BEA JRockit, Harmony, OpenJDK, etc... This JVM all conform to the JCK (those that have been officially tested that is), but have a lot of freedom when it comes to making things fast. GC is one of those areas that everyone invests in heavily. Using a hammer will often times destroy that effort.

Categories

Resources