I've been reading through a lot of the rookie Java questions on finalize() and find it kind of bewildering that no one has really made it plain that finalize() is an unreliable way to clean up resources. I saw someone comment that they use it to clean up Connections, which is really scary since the only way to come as close to a guarantee that a Connection is closed is to implement try (catch) finally.
I was not schooled in CS, but I have been programming in Java professionally for close to a decade now and I have never seen anyone implement finalize() in a production system ever. This still doesn't mean that it doesn't have its uses, or that people I've worked with have been doing it right.
So my question is, what use cases are there for implementing finalize() that cannot be handled more reliably via another process or syntax within the language?
Please provide specific scenarios or your experience, simply repeating a Java text book, or finalize's intended use is not enough, as is not the intent of this question.
You could use it as a backstop for an object holding an external resource (socket, file, etc). Implement a close() method and document that it needs to be called.
Implement finalize() to do the close() processing if you detect it hasn't been done. Maybe with something dumped to stderr to point out that you're cleaning up after a buggy caller.
It provides extra safety in an exceptional/buggy situation. Not every caller is going to do the correct try {} finally {} stuff every time. Unfortunate, but true in most environments.
I agree that it's rarely needed. And as commenters point out, it comes with GC overhead. Only use if you need that "belt and suspenders" safety in a long-running app.
I see that as of Java 9, Object.finalize() is deprecated! They point us to java.lang.ref.Cleaner and java.lang.ref.PhantomReference as alternatives.
finalize() is a hint to the JVM that it might be nice to execute your code at an unspecified time. This is good when you want code to mysteriously fail to run.
Doing anything significant in finalizers (basically anything except logging) is also good in three situations:
you want to gamble that other finalized objects will still be in a state that the rest of your program considers valid.
you want to add lots of checking code to all the methods of all your classes that have a finalizer, to make sure they behave correctly after finalization.
you want to accidentally resurrect finalized objects, and spend a lot of time trying to figure out why they don't work, and/or why they don't get finalized when they are eventually released.
If you think you need finalize(), sometimes what you really want is a phantom reference (which in the example given could hold a hard reference to a connection used by its referand, and close it after the phantom reference has been queued). This also has the property that it may mysteriously never run, but at least it can't call methods on or resurrect finalized objects. So it's just right for situations where you don't absolutely need to close that connection cleanly, but you'd quite like to, and the clients of your class can't or won't call close themselves (which is actually fair enough - what's the point of having a garbage collector at all if you design interfaces that require a specific action be taken prior to collection? That just puts us back in the days of malloc/free.)
Other times you need the resource you think you're managing to be more robust. For example, why do you need to close that connection? It must ultimately be based on some kind of I/O provided by the system (socket, file, whatever), so why can't you rely on the system to close it for you when the lowest level of resource is gced? If the server at the other end absolutely requires you to close the connection cleanly rather than just dropping the socket, then what's going to happen when someone trips over the power cable of the machine your code is running on, or the intervening network goes out?
Disclaimer: I've worked on a JVM implementation in the past. I hate finalizers.
A simple rule: never use finalizers.
The fact alone that an object has a finalizer (regardless what code it executes) is enough to cause considerable overhead for garbage collection.
From an article by Brian Goetz:
Objects with finalizers (those that
have a non-trivial finalize() method)
have significant overhead compared to
objects without finalizers, and should
be used sparingly. Finalizeable
objects are both slower to allocate
and slower to collect. At allocation
time, the JVM must register any
finalizeable objects with the garbage
collector, and (at least in the
HotSpot JVM implementation)
finalizeable objects must follow a
slower allocation path than most other
objects. Similarly, finalizeable
objects are slower to collect, too. It
takes at least two garbage collection
cycles (in the best case) before a
finalizeable object can be reclaimed,
and the garbage collector has to do
extra work to invoke the finalizer.
The result is more time spent
allocating and collecting objects and
more pressure on the garbage
collector, because the memory used by
unreachable finalizeable objects is
retained longer. Combine that with the
fact that finalizers are not
guaranteed to run in any predictable
timeframe, or even at all, and you can
see that there are relatively few
situations for which finalization is
the right tool to use.
The only time I've used finalize in production code was to implement a check that a given object's resources had been cleaned up, and if not, then log a very vocal message. It didn't actually try and do it itself, it just shouted a lot if it wasn't done properly. Turned out to be quite useful.
I've been doing Java professionally since 1998, and I've never implemented finalize(). Not once.
The accepted answer is good, I just wanted to add that there is now a way to have the functionality of finalize without actually using it at all.
Look at the "Reference" classes. Weak reference, Phantom Reference & Soft Reference.
You can use them to keep a reference to all your objects, but this reference ALONE will not stop GC. The neat thing about this is you can have it call a method when it will be deleted, and this method can be guaranteed to be called.
As for finalize:
I used finalize once to understand what objects were being freed. You can play some neat games with statics, reference counting and such--but it was only for analysis, but watch out for code like this (not just in finalize, but that's where you are most likely to see it):
public void finalize() {
ref1 = null;
ref2 = null;
othercrap = null;
}
It is a sign that somebody didn't know what they were doing. "Cleaning up" like this is virtually never needed. When the class is GC'd, this is done automatically.
If you find code like that in a finalize it's guaranteed that the person who wrote it was confused.
If it's elsewhere, it could be that the code is a valid patch to a bad model (a class stays around for a long time and for some reason things it referenced had to be manually freed before the object is GC'd). Generally it's because someone forgot to remove a listener or something and can't figure out why their object isn't being GC'd so they just delete things it refers to and shrug their shoulders and walk away.
It should never be used to clean things up "Quicker".
I'm not sure what you can make of this, but...
itsadok#laptop ~/jdk1.6.0_02/src/
$ find . -name "*.java" | xargs grep "void finalize()" | wc -l
41
So I guess the Sun found some cases where (they think) it should be used.
class MyObject {
Test main;
public MyObject(Test t) {
main = t;
}
protected void finalize() {
main.ref = this; // let instance become reachable again
System.out.println("This is finalize"); //test finalize run only once
}
}
class Test {
MyObject ref;
public static void main(String[] args) {
Test test = new Test();
test.ref = new MyObject(test);
test.ref = null; //MyObject become unreachableļ¼finalize will be invoked
System.gc();
if (test.ref != null) System.out.println("MyObject still alive!");
}
}
====================================
result:
This is finalize
MyObject still alive!
=====================================
So you may make an unreachable instance reachable in finalize method.
finalize() can be useful to catch resource leaks. If the resource should be closed but is not write the fact that it wasn't closed to a log file and close it. That way you remove the resource leak and give yourself a way to know that it has happened so you can fix it.
I have been programming in Java since 1.0 alpha 3 (1995) and I have yet to override finalize for anything...
You shouldn't depend on finalize() to clean up your resources for you. finalize() won't run until the class is garbage collected, if then. It's much better to explicitly free resources when you're done using them.
To highlight a point in the above answers: finalizers will be executed on the lone GC thread. I have heard of a major Sun demo where the developers added a small sleep to some finalizers and intentionally brought an otherwise fancy 3D demo to its knees.
Best to avoid, with possible exception of test-env diagnostics.
Eckel's Thinking in Java has a good section on this.
Be careful about what you do in a finalize(). Especially if you are using it for things like calling close() to ensure that resources are cleaned up. We ran into several situations where we had JNI libraries linked in to the running java code, and in any circumstances where we used finalize() to invoke JNI methods, we would get very bad java heap corruption. The corruption was not caused by the underlying JNI code itself, all of the memory traces were fine in the native libraries. It was just the fact that we were calling JNI methods from the finalize() at all.
This was with a JDK 1.5 which is still in widespread use.
We wouldn't find out that something went wrong until much later, but in the end the culprit was always the finalize() method making use of JNI calls.
Hmmm, I once used it to clean up objects that weren't being returned to an existing pool.
They were passed around a lot, so it was impossible to tell when they could safely be returned to the pool. The problem was that it introduced a huge penalty during garbage collection that was far greater than any savings from pooling the objects. It was in production for about a month before I ripped out the whole pool, made everything dynamic and was done with it.
When writing code that will be used by other developers that requires some sort of "cleanup" method to be called to free up resources. Sometimes those other developers forget to call your cleanup (or close, or destroy, or whatever) method. To avoid possible resource leaks you can check in the finalize method to ensure that the method was called and if it wasn't you can call it yourself.
Many database drivers do this in their Statement and Connection implementations to provide a little safety against developers who forget to call close on them.
Edit: Okay, it really doesn't work. I implemented it and thought if it fails sometimes that's ok for me but it did not even call the finalize method a single time.
I am not a professional programmer but in my program I have a case that I think to be an example of a good case of using finalize(), that is a cache that writes its content to disk before it is destroyed. Because it is not necessary that it is executed every time on destruction, it does only speed up my program, I hope that it i didn't do it wrong.
#Override
public void finalize()
{
try {saveCache();} catch (Exception e) {e.printStackTrace();}
}
public void saveCache() throws FileNotFoundException, IOException
{
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("temp/cache.tmp"));
out.writeObject(cache);
}
It can be handy to remove things that have been added to a global/static place (out of need), and need to be removed when the object is removed. For instance:
private void addGlobalClickListener() {
weakAwtEventListener = new WeakAWTEventListener(this);
Toolkit.getDefaultToolkit().addAWTEventListener(weakAwtEventListener, AWTEvent.MOUSE_EVENT_MASK);
}
#Override
protected void finalize() throws Throwable {
super.finalize();
if(weakAwtEventListener != null) {
Toolkit.getDefaultToolkit().removeAWTEventListener(weakAwtEventListener);
}
}
The accepted answer lists that closing a resource during finalize can be done.
However this answer shows that at least in java8 with the JIT compiler, you run into unexpected issues where sometimes the finalizer is called even before you finish reading from a stream maintained by your object.
So even in that situation calling finalize would not be recommended.
iirc - you can use finalize method as a means of implementing a pooling mechanism for expensive resources - so they don't get GC's too.
As a side note:
An object that overrides finalize() is treated specially by the garbage collector. Usually, an object is immediately destroyed during the collection cycle after the object is no longer in scope. However, finalizable objects are instead moved to a queue, where separate finalization threads will drain the queue and run the finalize() method on each object. Once the finalize() method terminates, the object will at last be ready for garbage collection in the next cycle.
Source: finalize() deprecated on java-9
The resources (File, Socket, Stream etc.) need to be closed once we are done with them. They generally have close() method which we generally call in finally section of try-catch statements. Sometimes finalize() can also be used by few developers but IMO that is not a suitable way as there is no guarantee that finalize will be called always.
In Java 7 we have got try-with-resources statement which can be used like:
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
// Processing and other logic here.
} catch (Exception e) {
// log exception
} finally {
// Just in case we need to do some stuff here.
}
In the above example try-with-resource will automatically close the resource BufferedReader by invoking close() method. If we want we can also implement Closeable in our own classes and use it in similar way. IMO it seems more neat and simple to understand.
Personally, I almost never used finalize() except in one rare circumstance: I made a custom generic-type collection, and I wrote a custom finalize() method that does the following:
public void finalize() throws Throwable {
super.finalize();
if (destructiveFinalize) {
T item;
for (int i = 0, l = length(); i < l; i++) {
item = get(i);
if (item == null) {
continue;
}
if (item instanceof Window) {
((Window) get(i)).dispose();
}
if (item instanceof CompleteObject) {
((CompleteObject) get(i)).finalize();
}
set(i, null);
}
}
}
(CompleteObject is an interface I made that lets you specify that you've implemented rarely-implemented Object methods like #finalize(), #hashCode(), and #clone())
So, using a sister #setDestructivelyFinalizes(boolean) method, the program using my collection can (help) guarantee that destroying a reference to this collection also destroys references to its contents and disposes any windows that might keep the JVM alive unintentionally. I considered also stopping any threads, but that opened a whole new can of worms.
Related
I need some solution that will help me tell for a some methods, in a case like this:
void myMethod(...)
{
MyObject obj = new MyObject();
// do stuff
}
if this method has ended or if obj is unreachable (which will indicate the method has ended).
I'm writing a small java agent, and I am hoping for some technique that either will let me know for sure this method ended or obj is unreachable... In my case the "do stuff" section doesn't use obj at all. It doesn't pass this variable somewhere else or adds it to some collection.
I know that with Weak/Soft/Phantom-References I can partially achieve this. If a GC is called, then by having:
void myMethod(...)
{
MyObject obj = new MyObject();
WeakReference objReference = new WeakReference(obj);
// do stuff
}
I can always verify in a different place:
if (objReference.get() == null) ...
However, this is only maybe true if GC occurred.
Is there any alternative way to achieve this?
For example, some marking the JVM may put on this variable since it is obvious this is a local that is definitely garbage-collectible...
I don't want to rely on ASM - and add a try-finally wrapper to all of these methods. Was hoping for a more subtle, reference based solution.
The only reliable way to do this ... that I can think of ... is to use callbacks / listeners; e.g.
public MyClass
void myMethod(Function<MyClass, Void> onCompletion) {
try {
// Do stuff
} finally {
onCompletion.apply(this);
}
}
You could also implement this using MethodHandles.tryFinally to create method handles for your method that implement the callback by wrapping the methods.
Anything based on Reference types is implicitly depending on garbage collection. This will be expensive, and you will have little control over when you get the notifications.
Is there any alternative way to achieve this? For example, some marking the JVM may put on this variable since it is obvious this is a local that is definitely garbage-collectible...
AFAIK, no there isn't. And the JVM / JIT do not do what you hypothesized; i.e. they don't mark an "obvious" local for finalization or collection ahead of a normal GC cycle.
Why don't they? Because it would make applications slower if that happened. The only benefit is that finalization / reference processing might happen sooner, but for a well-written application that would make no difference. A well-written program should not care when finalization / reference processing happens, since the timing is explicitly not guaranteed by the specs.
And it turns out that escape analysis doesn't help either:
https://shipilev.net/jvm-anatomy-park/18-scalar-replacement/
Now I am aware that the JIT may adjust the tables that tell the GC what is still in scope (see #Holger's comment; e.g. finalize() called on strongly reachable object in Java 8). But that doesn't change the method's instruction sequence. It is only the GC that pays attention to that information ... while the GC is running.
This question already has answers here:
Why is finalize not being called?
(4 answers)
Closed 6 years ago.
I am currently having an issue with objects of a class of mine not having their finalize() method called, despite only being stored in a ConcurrentHashMap as values, and the Object's UUID as the keys for the map.
Here is an example I have created (it isn't the one used in my actual project but this example also does not have the objects' finalize() methods called.
TestMain.class //The main class handling the HashMap
public class TestMain {
public static ConcurrentHashMap<String, WeakReference<Test>> map = new ConcurrentHashMap<String, WeakReference<Test>>();
public static void main(String args[]) {
map.put("Key1", new WeakReference<Test>(new Test("test 1", 2))); //This "Test" Object shouldn't be accessible anywhere besides the HashMap anymore, and therefore I want it to be "finalized" by the garbage collector.
System.out.println("DONE");
}
}
Test.class //The Object Class
public class Test {
public String string;
public int intt;
public Test(String string, int intt) {
this.string = string;
this.intt = intt;
}
#Override
protected void finalize() throws Throwable {
System.out.println("FINALIZED TEST CLASS: " + string);
super.finalize();
}
}
When the main method is run, all that is printed is "DONE" when I expected "FINALIZED TEST CLASS: Test 1" to also be printed prior to that. Is there something wrong with my code, or am I misunderstanding how finalize() works?
Also, I wish for this to work as I explain because I need the objects with the finalize() methods to be erased from the "map" Map and from memory as there will be several hundred of the object generated during my project's run duration, so I want the objects no longer in use to be cleared to make room for more new ones.
EDIT: I have seen elsewhere on the internet that people say the program might terminate before the garbage collector has a chance to dispose of the said objects. Therefore, I have attempted to let my program not terminate by adding a simple while(true){} loop and waited for a couple of minutes, and still did not see the message of the object being "finalized".
Any help is much appreciated, thank you.
The most likely explanation is that the GC never ran.
If the GC doesn't run, then objects won't be garbage collected.
If objects are not collected, they won't be finalized.
have attempted to let my program not terminate by adding a simple while(true){} loop and waited for a couple of minutes,
Waiting for the GC is not going to help. Normally it only runs when it >>needs to<< run; i.e. when one of the heap spaces exceeds a threshold of fullness.
You can force the GC to run by calling System.gc() ... but that is BAD PRACTICE. It will make your application inefficient and non-responsive.
It is also unwise to try to try to do anything in finalizers that has to be done in a timely fashion. You should design your code so that:
it doesn't matter if an object never gets finalized at all, and
it doesn't matter when an object gets finalized.
Why? Because you have little control over when objects get finalized ... and none at all if you don't call System.gc() ... which you should not do; see above.
In practice, finalizers are a feature of Java that should be used rarely, if at all. The only valid use-cases involve releasing external resources associated with resource objects that the application has not tidied up. Even then, it is better for the application to use "try with resources" (or a finally block) to clean up the resources explicitly.
As rightly mentioned in comments, there is no guarantee of finalize method being called.
The Java programming language does not guarantee which thread will
invoke the finalize method for any given object. It is guaranteed,
however, that the thread that invokes finalize will not be holding any
user-visible synchronization locks when finalize is invoked. If an
uncaught exception is thrown by the finalize method, the exception is
ignored and finalization of that object terminates.
Now coming back to your concern of manually disposing these objects after they are no longer accessible, you need not handle that, Java Garbage collector would handle that for you with it's automatic memory management. If you want to accelerate garbage collection, read on G1 Garbage collector.
i want to call destructor, when i close object, but i dont know how or when,.. I try whit finalize but its not calling. I dont know why
There is example code, i try with debugger but its help me..
class tralala(){
int i=0;
tralala(){
i=i+1;}
protected void finalize( ){
i=i-1;
}}
But it isnt call i dont know why. If anyone have got a suggestion plis help me. I am in the stuck at the moment, but i am not shure if java has got destructors.
Method finalize( ) "Ńalled by the garbage collector on an object when garbage collection determines that there are no more references to the object". So it will be called after garbage collector observe it to delete, but not immediately when object leave the scope.
I rly can't understand what do you mean as "close object"? You should find some other architecture solution to do what you want: maybe just call your method or raise some custom event with supplied handler when object leave scope ("close object").
I think you are trying to implement similar behavior like destructors. As destructors are not available into Java, I think you are trying to do with finalize.
But the finalize method is called when an object is about to get garbage collected. That can be at any time after it has become eligible for garbage collection.
Note that it's entirely possible that an object never gets garbage collected (and thus finalize is never called). This can happen when the object never becomes eligible for gc (because it's reachable through the entire lifetime of the JVM) or when no garbage collection actually runs between the time the object become eligible and the time the JVM stops running (this often occurs with your programs).
Read more about When is the finalize() method called in Java? and Why not to use finalize() method in java
And read How to implement object counter in Java SO QA for your solution. This is used for object counter. You can use same logic.
There is no destructors in java
class Tralala(){
int i=0;
Tralala(){
i=i+1;}
protected void reset( ){
i=i-1;
}}
call reset method when ever you want to destruct.
As a side note:There are lots of corrections in your code like naming conventions, formatting and also providing modifiers.
And I'm not getting, when finalize called, your instance is no more. Why you are resetting at that time,Since after that NO MORE OPERATIONS ON THAT OBJECT.
JAVA does not have destructors. JAVA has Garbage collectors. Garbage Collector runs as a thread and automatically destroys instances which do not have any active references.
it depends on your definition of closing the class.
you could implement the interface Closable so that eclipse could warn you about not closing the instance when needed.
it's different from finalize since you need to call it by yourself.
you could call close() in the finalize function in order to make sure it will get called when the instance is GC'ed .
The only thing I know about PhantomReference is,
If you use its get() method, it will always return null and not the object. What's the use of it?
By using PhantomReference, you make it sure that the object cannot be resurrected from finalize method.
But what is the use of this concept/class?
Have you ever used this in any of your project or do you have any example where we should use this?
I used PhantomReferences in a simplistic, very specialized kind of memory profiler to monitor object creation and destruction. I needed them to keep track of destruction. But the approach is out-dated. (It was written in 2004 targeting J2SE 1.4.) Professional profiling tools are much more powerful and reliable and the newer Java 5 features like JMX or agents and JVMTI can be used for that too.
PhantomReferences (always used together with the Reference queue) are superior to finalize which has some problems and should therefore be avoided. Mainly making objects reachable again. This could be avoided with the finalizer guardian idiom (-> read more in 'Effective Java'). So they are also the new finalize.
Furthermore, PhantomReferences
allow you to determine exactly when an object was removed from memory. They
are in fact the only way to determine that. This isn't generally that
useful, but might come in handy in certain very specific circumstances
like manipulating large images: if you know for sure that an image should be
garbage collected, you can wait until it actually is before attempting to
load the next image, and therefore make the dreaded OutOfMemoryError less
likely. (Quoted from enicholas.)
And as psd wrote first, Roedy Green has a good summary of references.
A general diced-up table explanation, from the Java Glossary.
Which of course coincides with the PhantomReference documentation:
Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
And last but not least, all the gory details (this is a good read): Java Reference Objects (or How I Learned to Stop Worrying and Love OutOfMemoryError).
Happy coding.
(But to answer the question, I've only ever used WeakReferences.)
Great explanation of Phantom Reference usage:
Phantom references are safe way to know an object has been removed
from memory. For instance, consider an application that deals with
large images. Suppose that we want to load a big image in to memory
when large image is already in memory which is ready for garbage
collected. In such case, we want to wait until the old image is
collected before loading a new one. Here, the phantom reference is
flexible and safely option to choose. The reference of the old image
will be enqueued in the ReferenceQueue once the old image object is
finalized. After receiving that reference, we can load the new image
in to memory.
I found a practical and useful use case of PhantomReference which is org.apache.commons.io.FileCleaningTracker in commons-io project. FileCleaningTracker will delete the physical file when its marker object is garbage collected.
Something to take note is the Tracker class which extends PhantomReference class.
THIS SHOULD BE OBSOLETE WITH JAVA 9!
Use java.util.Cleaner instead! (Or sun.misc.Cleaner on older JRE)
Original post:
I found that the use of PhantomReferences has nearly the same amount of pitfalls as finalizer methods (but a fewer problems once you get it right).
I have written a small solution (a very small framework to use PhantomReferences) for Java 8.
It allows to use lambda expressions as callbacks to be run after the object has been removed. You can register the callbacks for inner resources that should be closed.
With this I have found a solution that works for me as it makes it much more practical.
https://github.com/claudemartin/java-cleanup
Here's a small example to show how a callback is registered:
class Foo implements Cleanup {
//...
public Foo() {
//...
this.registerCleanup((value) -> {
try {
// 'value' is 'this.resource'
value.close();
} catch (Exception e) {
logger.warning("closing resource failed", e);
}
}, this.resource);
}
And then there is the even simpler method for auto-close, doing about the same as the above:
this.registerAutoClose(this.resource);
To answer your questions:
[ then whats the use of it ]
You can't clean up something that doesn't exist. But it could have had resources that still exist and need to be cleaned up so they can be removed.
But what is the use of this concept/class?
It's not necessarily to do anything with any effect other than debugging/logging. Or maybe for statistics.
I see it more like a notification service from the GC.
You could also want to use it to remove aggregated data that becomes irrelevant once the object is removed (but there are probably better solutions for that).
Examples often mention database connections to be closed, but I don't see how this is such a good idea as you couldn't work with transactions. An application framework will provide a much better solution for that.
Have you ever used this in any of your project, or do you have any example where we should use this? Or is this concept made just for interview point of view ;)
I use it mostly just for logging. So I can trace the removed elements and see how GC works and can be tweaked. I wouldn't run any critical code in this way. If something needs to be closed then it should be done in a try-with-resource-statement.
And I use it in unit tests, to make sure I don't have any memory leaks. The same way as jontejj does it. But my solution is a bit more general.
I used a PhantomReference in a unit test to verify that the code under test didn't keep unnessecary references to some object. (Original code)
import static com.google.common.base.Preconditions.checkNotNull;
import static org.fest.assertions.Assertions.assertThat;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import com.google.common.testing.GcFinalization;
/**
* Helps to test for memory leaks
*/
public final class MemoryTester
{
private MemoryTester()
{
}
/**
* A simple {#link PhantomReference} that can be used to assert that all references to it is
* gone.
*/
public static final class FinalizationAwareObject extends PhantomReference<Object>
{
private final WeakReference<Object> weakReference;
private FinalizationAwareObject(Object referent, ReferenceQueue<Object> referenceQueue)
{
super(checkNotNull(referent), referenceQueue);
weakReference = new WeakReference<Object>(referent, referenceQueue);
}
/**
* Runs a full {#link System#gc() GC} and asserts that the reference has been released
* afterwards
*/
public void assertThatNoMoreReferencesToReferentIsKept()
{
String leakedObjectDescription = String.valueOf(weakReference.get());
GcFinalization.awaitFullGc();
assertThat(isEnqueued()).as("Object: " + leakedObjectDescription + " was leaked").isTrue();
}
}
/**
* Creates a {#link FinalizationAwareObject} that will know if {#code referenceToKeepTrackOff}
* has been garbage collected. Call
* {#link FinalizationAwareObject#assertThatNoMoreReferencesToReferentIsKept()} when you expect
* all references to {#code referenceToKeepTrackOff} be gone.
*/
public static FinalizationAwareObject createFinalizationAwareObject(Object referenceToKeepTrackOff)
{
return new FinalizationAwareObject(referenceToKeepTrackOff, new ReferenceQueue<Object>());
}
}
And the test:
#Test
public void testThatHoldingOnToAnObjectIsTreatedAsALeak() throws Exception
{
Object holdMeTight = new String("Hold-me-tight");
FinalizationAwareObject finalizationAwareObject = MemoryTester.createFinalizationAwareObject(holdMeTight);
try
{
finalizationAwareObject.assertThatNoMoreReferencesToReferentIsKept();
fail("holdMeTight was held but memory leak tester did not discover it");
}
catch(AssertionError expected)
{
assertThat(expected).hasMessage("[Object: Hold-me-tight was leaked] expected:<[tru]e> but was:<[fals]e>");
}
}
It is common to use WeakReference where PhantomReference is more appropriate. This avoids certain problems of being able to resurrect objects after a WeakReference is cleared/enqueued by the garbage collector. Usually the difference doesn't matter because people are not playing silly buggers.
Using PhantomReference tends to be a bit more intrusive because you can't pretend that the get method works. You can't, for example, write a Phantom[Identity]HashMap.
I used it in the early days of Android. Back them a BitmapDrawable had an underlying Bitmap that used memory that was not allocated in the Java Heap space, which meant that you were using memory, but the JVM didn't feel the memory pressure. The symptom was the app would crash by running out of memory, but you'd never find that your finalizer was called (or that there hadn't been a garbage collection sweep at all).
So I created a subclass of PhantomReference that had a hard reference to the Bitmap (class variable). The PhantomReference itself pointed to the BitmapDrawable.
When the phantom reference would come off the queue indicating that the BitmapDrawable was no longer reachable, I'd call the release method on the Bitmap which released the memory that was outside of the vm heap space.
It worked great, it more or less completely removed the out of memory failures that occurred because of that weird memory model on early Android.
Android later changed the memory model to load bitmaps into the JVM heap, btw, because you actually want your vm to feel memory pressure if the app is running out of memory. It was definitely a "Black Diamond" situation to have to release the memory like this and I doubt most app developers realized that Garbage Collection wasn't going to help them because the memory was outside the view of the Garbage Collector. They probably just viewed it as an Android bug.
if you use its get() method it will always return null, and not the
object. [ then whats the use of it ]
The useful methods to call (rather than get()) would be isEnqueued() or referenceQueue.remove(). You would call these methods to perform some action that needs to take place on the final round of garbage collection of the object.
The first time around is when the object has its finalize() method called, so you could put closing hooks there too. However, as others have stated, there are probably more sure ways of performing clean up or whatever action needs to take place pre and post garbage collection or, more generally, upon end-of-life of the object.
I found another practical use of PhantomReferences in LeakDetector class of Jetty.
Jetty uses LeakDetector class to detect if the client code acquires a resource but never releases it and the LeakDetector class uses the PhantomReferences for this purpose.
Here is a generic example of using it: In this case, for some Swing code in a vector editor, where it's easy to create tens of thousands of AffineTransform instances inside the paint loop, when they are easily recycled and reused, and this showed itself to be a significant bottleneck in profiling. I've used the same pattern to reuse CharBuffer instances when processing log files line-by line. Basically the pattern is: You have some data structure which is expensive to create, and it is one you can completely reset the state on, rather than create a new one every time. So, you create a PhantomReference subclass that strongly references the object you want to recycle and reuse, whose referent is a thing that could be referencing the object; to track when it is safe to recycle an object, you either
Return a facade for the object, that implements the same interface or something close enough (e.g. a CharSequence implementation that wraps a CharBuffer), and use that as the referent of your PhantomReference or
Callers pass you a reference to themselves and so you can recycle an object when the caller goes out of scope
In other words, the pattern here you're asking the queue to tell you when every object that could know about some cached thing is gone, so you can make it available for reuse to another caller.
The only thing I know about PhantomReference is,
If you use its get() method, it will always return null and not the object. What's the use of it?
By using PhantomReference, you make it sure that the object cannot be resurrected from finalize method.
But what is the use of this concept/class?
Have you ever used this in any of your project or do you have any example where we should use this?
I used PhantomReferences in a simplistic, very specialized kind of memory profiler to monitor object creation and destruction. I needed them to keep track of destruction. But the approach is out-dated. (It was written in 2004 targeting J2SE 1.4.) Professional profiling tools are much more powerful and reliable and the newer Java 5 features like JMX or agents and JVMTI can be used for that too.
PhantomReferences (always used together with the Reference queue) are superior to finalize which has some problems and should therefore be avoided. Mainly making objects reachable again. This could be avoided with the finalizer guardian idiom (-> read more in 'Effective Java'). So they are also the new finalize.
Furthermore, PhantomReferences
allow you to determine exactly when an object was removed from memory. They
are in fact the only way to determine that. This isn't generally that
useful, but might come in handy in certain very specific circumstances
like manipulating large images: if you know for sure that an image should be
garbage collected, you can wait until it actually is before attempting to
load the next image, and therefore make the dreaded OutOfMemoryError less
likely. (Quoted from enicholas.)
And as psd wrote first, Roedy Green has a good summary of references.
A general diced-up table explanation, from the Java Glossary.
Which of course coincides with the PhantomReference documentation:
Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
And last but not least, all the gory details (this is a good read): Java Reference Objects (or How I Learned to Stop Worrying and Love OutOfMemoryError).
Happy coding.
(But to answer the question, I've only ever used WeakReferences.)
Great explanation of Phantom Reference usage:
Phantom references are safe way to know an object has been removed
from memory. For instance, consider an application that deals with
large images. Suppose that we want to load a big image in to memory
when large image is already in memory which is ready for garbage
collected. In such case, we want to wait until the old image is
collected before loading a new one. Here, the phantom reference is
flexible and safely option to choose. The reference of the old image
will be enqueued in the ReferenceQueue once the old image object is
finalized. After receiving that reference, we can load the new image
in to memory.
I found a practical and useful use case of PhantomReference which is org.apache.commons.io.FileCleaningTracker in commons-io project. FileCleaningTracker will delete the physical file when its marker object is garbage collected.
Something to take note is the Tracker class which extends PhantomReference class.
THIS SHOULD BE OBSOLETE WITH JAVA 9!
Use java.util.Cleaner instead! (Or sun.misc.Cleaner on older JRE)
Original post:
I found that the use of PhantomReferences has nearly the same amount of pitfalls as finalizer methods (but a fewer problems once you get it right).
I have written a small solution (a very small framework to use PhantomReferences) for Java 8.
It allows to use lambda expressions as callbacks to be run after the object has been removed. You can register the callbacks for inner resources that should be closed.
With this I have found a solution that works for me as it makes it much more practical.
https://github.com/claudemartin/java-cleanup
Here's a small example to show how a callback is registered:
class Foo implements Cleanup {
//...
public Foo() {
//...
this.registerCleanup((value) -> {
try {
// 'value' is 'this.resource'
value.close();
} catch (Exception e) {
logger.warning("closing resource failed", e);
}
}, this.resource);
}
And then there is the even simpler method for auto-close, doing about the same as the above:
this.registerAutoClose(this.resource);
To answer your questions:
[ then whats the use of it ]
You can't clean up something that doesn't exist. But it could have had resources that still exist and need to be cleaned up so they can be removed.
But what is the use of this concept/class?
It's not necessarily to do anything with any effect other than debugging/logging. Or maybe for statistics.
I see it more like a notification service from the GC.
You could also want to use it to remove aggregated data that becomes irrelevant once the object is removed (but there are probably better solutions for that).
Examples often mention database connections to be closed, but I don't see how this is such a good idea as you couldn't work with transactions. An application framework will provide a much better solution for that.
Have you ever used this in any of your project, or do you have any example where we should use this? Or is this concept made just for interview point of view ;)
I use it mostly just for logging. So I can trace the removed elements and see how GC works and can be tweaked. I wouldn't run any critical code in this way. If something needs to be closed then it should be done in a try-with-resource-statement.
And I use it in unit tests, to make sure I don't have any memory leaks. The same way as jontejj does it. But my solution is a bit more general.
I used a PhantomReference in a unit test to verify that the code under test didn't keep unnessecary references to some object. (Original code)
import static com.google.common.base.Preconditions.checkNotNull;
import static org.fest.assertions.Assertions.assertThat;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import com.google.common.testing.GcFinalization;
/**
* Helps to test for memory leaks
*/
public final class MemoryTester
{
private MemoryTester()
{
}
/**
* A simple {#link PhantomReference} that can be used to assert that all references to it is
* gone.
*/
public static final class FinalizationAwareObject extends PhantomReference<Object>
{
private final WeakReference<Object> weakReference;
private FinalizationAwareObject(Object referent, ReferenceQueue<Object> referenceQueue)
{
super(checkNotNull(referent), referenceQueue);
weakReference = new WeakReference<Object>(referent, referenceQueue);
}
/**
* Runs a full {#link System#gc() GC} and asserts that the reference has been released
* afterwards
*/
public void assertThatNoMoreReferencesToReferentIsKept()
{
String leakedObjectDescription = String.valueOf(weakReference.get());
GcFinalization.awaitFullGc();
assertThat(isEnqueued()).as("Object: " + leakedObjectDescription + " was leaked").isTrue();
}
}
/**
* Creates a {#link FinalizationAwareObject} that will know if {#code referenceToKeepTrackOff}
* has been garbage collected. Call
* {#link FinalizationAwareObject#assertThatNoMoreReferencesToReferentIsKept()} when you expect
* all references to {#code referenceToKeepTrackOff} be gone.
*/
public static FinalizationAwareObject createFinalizationAwareObject(Object referenceToKeepTrackOff)
{
return new FinalizationAwareObject(referenceToKeepTrackOff, new ReferenceQueue<Object>());
}
}
And the test:
#Test
public void testThatHoldingOnToAnObjectIsTreatedAsALeak() throws Exception
{
Object holdMeTight = new String("Hold-me-tight");
FinalizationAwareObject finalizationAwareObject = MemoryTester.createFinalizationAwareObject(holdMeTight);
try
{
finalizationAwareObject.assertThatNoMoreReferencesToReferentIsKept();
fail("holdMeTight was held but memory leak tester did not discover it");
}
catch(AssertionError expected)
{
assertThat(expected).hasMessage("[Object: Hold-me-tight was leaked] expected:<[tru]e> but was:<[fals]e>");
}
}
It is common to use WeakReference where PhantomReference is more appropriate. This avoids certain problems of being able to resurrect objects after a WeakReference is cleared/enqueued by the garbage collector. Usually the difference doesn't matter because people are not playing silly buggers.
Using PhantomReference tends to be a bit more intrusive because you can't pretend that the get method works. You can't, for example, write a Phantom[Identity]HashMap.
I used it in the early days of Android. Back them a BitmapDrawable had an underlying Bitmap that used memory that was not allocated in the Java Heap space, which meant that you were using memory, but the JVM didn't feel the memory pressure. The symptom was the app would crash by running out of memory, but you'd never find that your finalizer was called (or that there hadn't been a garbage collection sweep at all).
So I created a subclass of PhantomReference that had a hard reference to the Bitmap (class variable). The PhantomReference itself pointed to the BitmapDrawable.
When the phantom reference would come off the queue indicating that the BitmapDrawable was no longer reachable, I'd call the release method on the Bitmap which released the memory that was outside of the vm heap space.
It worked great, it more or less completely removed the out of memory failures that occurred because of that weird memory model on early Android.
Android later changed the memory model to load bitmaps into the JVM heap, btw, because you actually want your vm to feel memory pressure if the app is running out of memory. It was definitely a "Black Diamond" situation to have to release the memory like this and I doubt most app developers realized that Garbage Collection wasn't going to help them because the memory was outside the view of the Garbage Collector. They probably just viewed it as an Android bug.
if you use its get() method it will always return null, and not the
object. [ then whats the use of it ]
The useful methods to call (rather than get()) would be isEnqueued() or referenceQueue.remove(). You would call these methods to perform some action that needs to take place on the final round of garbage collection of the object.
The first time around is when the object has its finalize() method called, so you could put closing hooks there too. However, as others have stated, there are probably more sure ways of performing clean up or whatever action needs to take place pre and post garbage collection or, more generally, upon end-of-life of the object.
I found another practical use of PhantomReferences in LeakDetector class of Jetty.
Jetty uses LeakDetector class to detect if the client code acquires a resource but never releases it and the LeakDetector class uses the PhantomReferences for this purpose.
Here is a generic example of using it: In this case, for some Swing code in a vector editor, where it's easy to create tens of thousands of AffineTransform instances inside the paint loop, when they are easily recycled and reused, and this showed itself to be a significant bottleneck in profiling. I've used the same pattern to reuse CharBuffer instances when processing log files line-by line. Basically the pattern is: You have some data structure which is expensive to create, and it is one you can completely reset the state on, rather than create a new one every time. So, you create a PhantomReference subclass that strongly references the object you want to recycle and reuse, whose referent is a thing that could be referencing the object; to track when it is safe to recycle an object, you either
Return a facade for the object, that implements the same interface or something close enough (e.g. a CharSequence implementation that wraps a CharBuffer), and use that as the referent of your PhantomReference or
Callers pass you a reference to themselves and so you can recycle an object when the caller goes out of scope
In other words, the pattern here you're asking the queue to tell you when every object that could know about some cached thing is gone, so you can make it available for reuse to another caller.