I know that the GC collects objects that have no references pointing to the object in question, but what happens in the event of listener objects?
Suppose you have an AnimationDelegate that listens to data from a DataSupplier. When the DataSupplier recieves data and fires off the event to the AnimationDelegate, the delegate will then invalidate (/update/redraw etc...) a Graphic. Now say the screen is disabled, removed or, through various means, the graphic can no longer draw and is collected. The AnimationDelegate is still registered to the DataSupplier. How will the GC know to collect it? Should one unregister the delegate in the graphics finalize() method?
I'm afraid the answer won't fit the format :) Start with this article by Brian Goetz: he's a perfect person to read if you're interested in GC.
Basically, as soon as object is not reachable from active threads, it's collected. The actual algorithms vary even within one JVM, but the point stays the same: what's not reachable is a garbage. What's reachable is not a garbage. Easy.
GC will not collect the Graphic in your example, as it's reachable from AnimationDelegate, which in turn is reachable (via subscription) from DataSupplier which is supposed to be reachable from some active thread. So the answer will be: your assumptions are wrong; GC will not collect anything here.
To answer your question, unsubscribe everything you don't need.
As #rfeak rightfully says, finalize() is a big no-no. It's almost impossible to use it properly, and it's way too easy to use it wrong. That said,it's OK to use it as a backup solution when you need to free resources. But generally your application has to be able to work just fine even if finalize() never gets called.
It all depends on the JVM you're using and the GC. Most default GC from the JDK use the so called "tracing collectors", which simply start at a given root set of objects and trace all the objects reachable from that set. All the other objects in memory are seen as garbage and deleted. So circular references aren't really a problem unless one of the objects is reachable from the root set.
What is the root set of objects? Well if memory serves right roots can be found in: program registers, local variables in each thread's stack and static variables.
To see if your objects will be GC'd we would know more about the design of your application.
#Edit: Oh and I almost forgot: Memory Management in the JavaHotSpot™ Virtual Machine. This is a pretty good overview of how it all works.
It will only know if you have removed the references (nulled them out).
However, don't do this on finalize(). Finalize is bad bad bad. There should be other lifecycle methods available for cleaning up listener(observer) type objects.
By the way, observer pattern is notorious for creating memory leaks because the GC couldn't collect due to lingering references.
Related
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...
Does java collect the garbage-signed things as objects?
If yes, can i tell java to direct them to one of my hashtables(accepts objects right?) programmatically?
I am curious about this functionality.I know System.gc() is the command but how can i achieve first question? Can i?
myTrashBin=System.gc().getObjectList(); //???
If not, may be there could be a way to create this functionality by custom classes.
Last question: how can we override System.gc() ?
Thanks.
This isn't under your control. If your objects are unreachable then GC will collect these. System.gc() is nothing more than a hint, and can't be relied upon.
finalize() may be of interest, but read the answers to this question to understand limitations etc. PhantomReferences may also be of interest.
I think you can achieve something like that if you implement the Finalize method and writing the code there: maybe adding the object to a custom list
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#finalize%28%29
System.gc() issues a call for the garbage collector but that's all there is to it. It might rise its priority and it might collect your items sooner, but there is no guarantee, as the docs say:
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.
You're better off taking other approaches such as the finalize() method or managing a reference counter in your objects so when it hits zero you know it is elegible to be collected. Check this link out.
Java uses managed memory. This means the JVM manages it because you don't want to ;)
can i tell java to direct them to one of my hashtables(accepts objects right?) programmatically?
You can progammatically get all the objects which would be cleaned up if they are referenced via a WeakReference.
how can we override System.gc() ?
You can't. In fact its only a hint as its not guaranteed to do anything.
Read in some blog that GC in Android happens on main(UI) thread, this may create sluggishness in UI screen depending on the frequency of GC execution.
Hence I was wondering will it be a good idea if I manually release objects(by assigning null value) which has no further use for me.
This way we may avoid multiple execution of GC in the application.
Please share your thoughts.
Thanks,
sku
There's no such thing as "manually releasing objects" -- at least not in any way that's meaningful to GC. An object doesn't immediately get freed/collected/whatever when you lose all references to it; it just becomes eligible for collection. GC is what actually does the releasing of the object, and it does so when it feels like doing so.
The only real way to keep the GC from working so hard is to create fewer objects, particularly temporary objects. Less garbage == less collection.
Releasing (dereferencing) objects for which you have no further use is always a good idea. You can also use SoftReference, WeakReference and/or WeakHashMap to help the GC pick up stuff that you don't mind going away if the system needs space.
There's more information about Android's GC system here.
I have a cache which has soft references to the cached objects. I am trying to write a functional test for behavior of classes which use the cache specifically for what happens when the cached objects are cleared.
The problem is: I can't seem to reliably get the soft references to be cleared. Simply using up a bunch of memory doesn't do the trick: I get an OutOfMemory before any soft references are cleared.
Is there any way to get Java to more eagerly clear up the soft references?
Found here:
"It is guaranteed though that all
SoftReferences will get cleared before
OutOfMemoryError is thrown, so they
theoretically can't cause an OOME."
So does this mean that the above scenario MUST mean I have a memory leak somewhere with some class holding a hard reference on my cached object?
The problem is: I can't seem to
reliably get the soft references to be
cleared.
This is not unique to SoftReferences. Due to the nature of garbage collection in Java, there is no guarantee that anything that is garbage-collectable will actually be collected at any point in time. Even with a simple bit of code:
Object temp = new Object();
temp = null;
System.gc();
there is no guarantee that the Object instantiated in the first line is garbage collected at this, or in fact any point. It's simply one of the things you have to live with in a memory-managed language, you're giving up declarative power over these things. And yes, that can make it hard to definitively test for memory leaks at times.
That said, as per the Javadocs you quoted, SoftReferences should definitely be cleared before an OutOfMemoryError is thrown (in fact, that's the entire point of them and the only way they differ from the default object references). It would thus sound like there is some sort of memory leak in that you're holding onto harder references to the objects in question.
If you use the -XX:+HeapDumpOnOutOfMemoryError option to the JVM, and then load the heap dump into something like jhat, you should be able to see all the references to your objects and thus see if there are any references beside your soft ones. Alternatively you can achieve the same thing with a profiler while the test is running.
There is also the following JVM parameter for tuning how soft references are handled:
-XX:SoftRefLRUPolicyMSPerMB=<value>
Where 'value' is the number of milliseconds a soft reference will remain for every free Mb of memory. The default is 1s/Mb, so if an object is only soft reachable it will last 1s if only 1Mb of heap space is free.
You can force all SoftReferences to be cleared in your tests with this piece of code.
If you really wanted to, you can call clear() on your SoftReference to clear it.
That said, if the JVM is throwing an OutOfMemoryError and your SoftReference has not been cleared yet, then this means that you must have a hard reference to the object somewhere else. To do otherwise would invalidate the contract of SoftReference. Otherwise, you are never guaranteed that the SoftReference is cleared: as long as there is still memory available, the JVM does not need to clear any SoftReferences. On the other hand, it is allowed to clear them next time it does a GC cycle, even if it doesn't need to.
Also, you can consider looking into WeakReferences since the VM tends to be more aggressive in clear them. Technically, the VM isn't ever required to clear a WeakReference, but it is supposed to clean them up next time it does a GC cycle if the object would otherwise be considered dead. If your are trying to test what happens when your cache is cleared, using WeakReferences should help your entries go away faster.
Also, remember that both of these are dependent on the JVM doing a GC cycle. Unfortunately, there is no way to guarantee that one of those ever happens. Even if you call System.gc(), the garbage collector may decide that it is doing just peachy and choose to do nothing.
In a typical JVM implementation (SUN) you need to trigger a Full GC more than once to get the Softreferences cleaned. The reason for that is because Softreferences require the GC to do more work, because for example of a mechanism that allows you to get notified when the objects are reclaimed.
IMHO using a lot of sofreferences in an application server is evil, because the developer has not much control over when they are released.
Garbage collection and other references like soft references are non deterministic this it's not really possible to reliable do stuff so that soft references are definitely cleared at that point so your test can judge how yourcache reacts. I would suggest you simulate the reference clearing in more definite way by mocking etc - your tests will be reproducable and more valuable rather than just Hopi g for the GC to clean up references. Using the latter approach is a really bad thing to do and willjust introduce additional problems rather than help you improve the quality of your cache and it's collaborating components.
From the documentation and my experience I'd say yes: you must have a reference somewhere else.
I'd suggest using a debugger that can show you all references to an object (such as Eclipse 3.4 when debugging Java 6) and just check when the OOM is thrown.
If you use eclipse, there is this tool named Memory Analyzer that makes heap dump debugging easier.
Does the cached object have a finalizer? The finalizer will create new strong references to the object, so even if the SoftReference is cleared the memory will not be reclaimed until a later GC cycle
If you have a cache which is a Map of SoftReferences and you want them cleared you can just clear() the map and they will all be cleaned up (including their references)
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.