How to log when the finalize method was not called? - java

I am not using the finalize method in my application but this question is out of curiosity.
Assume that there is finalize method in a class and I would like to log a warning message that finalize was not called.
How to do this ?
Any tips ?

Two possibilities--In either case, you need a singleton collection.
1) When each object is constructed add a unique key (String) that identifies the object--(but not the object itself!) to the collection. When the finalizer is called, remove it's key from the collection.
At any given time, outstanding instances are available in the collection.
2) Okay, you CAN add the object itself to the collection if you really want to, but the collection must be a collection of the proper reference class. This is harder and requires a little research--look into reference classes (WeakReference/PhantomReference/??). I haven't looked at them for a few years and forget exactly which one does what, but this is exactly the kind of work the Reference classes were made for.
Be careful with 2, I think there is a chance that iterating through the reference collection could resurrect a dead class or stop one from being collected.
The reason for both caveats is that if you store a reference in a normal collection it will never be eligible for collection so no finalizer will ever be called.

The JVM guarantees that the method will be called before the object is disposed, as per JLS 12.6. Finalization of Class Instances:
The Java programming language does not specify how soon a finalizer will be invoked, except to say that it will happen before the storage for the object is reused.
You are trying to prove that JVM does not follow the JLS, which would be a bug.
Looking at Azul Zulu OpenJDK 11 source we can observe that finaliztions are run with java.lang.ref.Finalizer object which in turn uses jdk.internal.misc.JavaLangAccess.invokeFinalize(Object) method to call Object.finalize().
JavaLangAccess instance is obtained from jdk.internal.misc.SharedSecrets which allows to setup a custom instance of JavaLangAccess. Perhaps you could create your own JavaLangAccess instance with additional logging in invokeFinalize() method?

Related

Freeing memory used by no longer needed objects in instance controlled classes in java

Consider the following scenario.
You are building a class, in java, where the fundamental semantics of the class demand that no two instances of the class be equal in value unless they are in fact the same object (see instance-controlled classes in Effective Java by Joshua Bloch). In a sense this is like a very large enum (possibly hundreds of millions of "constants") that are not known until runtime. So, to recap, you want the class to ensure that that there are no "equal" instances on the heap. There may be lots of references to a particular object on the heap, but no extraneous equal objects. This can obviously be done in code but it seems to me that there is a major flaw that I have not seen addressed anywhere, including in Effective Java. It seems to me that in order to make this guarantee the instance-controlled class must keep a reference to every instance of itself that has EVER been created at any point during program execution and can NEVER "delete" one of those objects because it can never know that there are no longer any "pointers" to that object (besides the one that it itself keeps). In other words, if you think about this in the context of reference-counting, there will come some point in the program where the only reference to the object is the one held by the class itself (the one that says, "this was created at some point"). At that point you would like to release the memory associated with the object, but you can't because that one pointer that is left has no way of knowing that it is the last one.
Is there a good approach to providing instance-controlled classes which can also free no-longer-needed memory?
Update: So, I think I've found something that might help. It turns out java has a java.lang.ref class that provides weak references. From wikipedia: "A WeakReference is used to implement weak maps. An object that is not strongly or softly reachable, but is referenced by a weak reference is called "weakly reachable". A weakly reachable object is garbage collected in the next collection cycle. This behavior is used in the class java.util.WeakHashMap. A weak map allows the programmer to put key/value pairs in the map and not worry about the objects taking up memory when the key is no longer reachable anywhere else. Another possible application of weak references is the string intern pool. Semantically, a weak reference means "get rid of this object when nothing else references it at the next garbage collection."
You need to use one of the special reference objects, like a weak reference. These were created just to support the use case you mention.
As you create an object, you search your collection of weak references to see if the object already exists; if it does, you return a regular reference to it. If it does not, you create it and return a regular reference, and add a weak reference to it to your collection.
Your weak reference will notify you when it is not used anywhere outside of your collection; you can then remove it from your collection. With no references any where, it can then be garbage collected.
The general concept is called a "canonicalizing cache."
The WeakHashMap class is a shortcut that does some of the plumbing for this for you.
It is not clear what your requirements are. You say you want hundreds of millions of entires. This suggests that a database or NoSQL is the best way to store this.
To ensure you have no duplicates, you can keep track of referenced objects which have been retained with a WeakHashMap.

Finalize() cleanup vs. Garbage Collector removing an object from memory

I was reading about the finalize() method and was curious:
What is the difference between the task of cleaning up objects ( setting them to NULL ) in finalize, and removing an object from memory?
What is the difference between the task of cleaning up objects (
setting them to NULL ) in finialize
setting to null removes ONE reference to the object.
if NO more references to an object exists, the garbage collector is allowed (not required) to remove the object
and removing an object from memory?
there is NO explicit way in java to remove (destroy, delete) an object.
The garbage collector will do it when he likes.
Especially the time from removing the last reference to remove/destroy the object is indefinite
There is NO need to set references to null in finalize method.
when the garbage collector call finalize the objects and its references will gone soon anyway.
I never wrote an own finalize method during my very long java experience.
The rare occasion in which it make sense to wrote an own finalize method appear if your object is dealing with os-resources. However, in general you use standard packages for os accesss
You don't "clean up" an object when you set it to null, you're just setting the reference to null, consider:
Object a = new Object();
Object b = a;
a = null;
System.out.println(b);
Once an object loses all references, it will be collected on the next GC pass. Finalize is a method that gets called when this happens, and you should avoid using it.
Just don't keep extra references around and let the GC do it's job.
finalize() is called by garbage collector when an object has no more references. You can override it and best practice is to use it in a try-catch-finally block to free non java resources like files. Anyway if you use it this way you should also call super.finalize() to ensure class hierarchy finalization.
This method is always for advanced use and shouldn't be used in normal production code. Free your resources in finally clauses in methods using those resources.

is there a way to recycle a complex java object once the GC has decided it is unreachable

In C++ I use reference counted objects to impplement a for of "auto" recycling object pool
SmartPointer<ObjType> object = pool.getObject(); // hold reference
// ... do stuff with object over time.
object = nullptr; // that is when reference
// count goes to 0
-- Now I have on the C++ objects an "onFinalRelease()" method which gets called when the refcount reaches 0. I can overide this ( default is delete(this) ) to auto-recycle objects rather than destroying them.
The question is can I implement this pattern with some combination of java reference types and reference pools. Of course this is for a type of large complex expensive to create object where it makes sense. That is I want to do:
SomeReference r = referenceQueue.getReference();
pool.recycle(r.takeBackUnusedObjectFromGC()); // ??????????????????????????
This would be real nice :)
You can use PhantomReferences to do something like this. Have an interface (proxy) object with a (strong, unidirectional) reference to the expensive object. Also keep a strong reference to the expensive object in your pool management. Keep a PhantomReference to the interface object. Once the PhantomReference comes up on its ReferenceQueue you know for sure that the expensive object is not being used through an interface object (even allowing for finalisation). The expensive object can now be reused with a new interface object.
However, it probably isn't worth it.
With reference counting, there is a clearly defined time when an object becomes garbage - when the reference count goes to zero. With Java's garbage collection, there is no guarantee that a given object will ever be garbage collected, even if there are no more strong references to it.
Implementing your own reference counter by hand is the best solution I can think of.
Java has something similar called the finalize method. Unfortunately, once it runs for an object, there's no going back. In addition, it's not even guaranteed to run.
You best bet might be to create a pool of objects and track yourself whether they can be reused or not. Apache Commons Pool might be useful for this.
This class may be what you're looking for:
https://commons.apache.org/proper/commons-pool/apidocs/org/apache/commons/pool2/impl/SoftReferenceObjectPool.html

Does variable = null set it for garbage collection

Help me settle a dispute with a coworker:
Does setting a variable or collection to null in Java aid in garbage collection and reducing memory usage? If I have a long running program and each function may be iteratively called (potentially thousands of times): Does setting all the variables in it to null before returning a value to the parent function help reduce heap size/memory usage?
That's old performance lore. It was true back in 1.0 days, but the compiler and the JVM have been improved to eliminate the need (if ever there was one). This excellent IBM article gets into the details if you're interested: Java theory and practice: Garbage collection and performance
From the article:
There is one case where the use of explicit nulling is not only helpful, but virtually required, and that is where a reference to an object is scoped more broadly than it is used or considered valid by the program's specification. This includes cases such as using a static or instance field to store a reference to a temporary buffer, rather than a local variable, or using an array to store references that may remain reachable by the runtime but not by the implied semantics of the program.
Translation: "explicitly null" persistent objects that are no longer needed. (If you want. "Virtually required" too strong a statement?)
The Java VM Spec
12.6.1 Implementing Finalization
Every object can be characterized by two attributes: it may be reachable, finalizer-reachable, or unreachable, and it may also be unfinalized, finalizable, or finalized.
A reachable object is any object that can be accessed in any potential continuing computation from any live thread. Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.
Discussion
Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage.
The object is reachable if it can be involved in any potential continuing computation. So if your code refers to a local variable, and nothing else refers to it, then you might cause the object to be collected by setting it to null. This would either give a null pointer exception, or change the behaviour of your program, or if it does neither you didn't need the variable in the first place.
If you are nulling out a field or an array element, then that can possibly make sense for some applications, and it will cause the memory to be reclaimed faster. Once case is creating a large array to replace an existing array referenced by a field in a class - if the field in nulled before the replacement is created, then it may relieve pressure on the memory.
Another interesting feature of Java is that scope doesn't appear in class files, so scope is not relevant to reachability; these two methods create the same bytecode, and hence the VM does not see the scope of the created object at all:
static void withBlock () {
int x = 1;
{
Object a = new Object();
}
System.out.println(x+1);
}
static void withoutBlock () {
int x = 1;
Object a = new Object();
System.out.println(x+1);
}
Not necessarily. An object becomes eligible for garbage collection when there are no live threads anymore that hold a reference to the object.
Local variables go out of scope when the method returns and it makes no sense at all to set local variables to null - the variables disappear anyway, and if there's nothing else that holds a reference the objects that the variables referred to, then those objects become eligible for garbage collection.
The key is not to look at just variables, but look at the objects that those variables refer to, and find out where those objects are referenced by your program.
It is useless on local variables, but it can be useful/needed to clear up instance variables that are not required anymore (e.g. post-initialization).
(Yeah yeah, I know how to apply the Builder pattern...)
That could only make some sense in some scenario like this:
public void myHeavyMethod() {
List hugeList = loadHugeListOfStuff(); // lots of memory used
ResultX res = processHugeList(hugeList); // compute some result or summary
// hugeList = null; // we are done with hugeList
...
// do a lot of other things that takes a LOT of time (seconds?)
// and which do not require hugeList
...
}
Here it could make some benefit to uncomment the hugeList = null line, I guess.
But it would certainly make more sense to rewrite the method (perhaps refactoring into two,
or specifying an inner scope).
Setting an object reference to null only makes it eligible for garbage collection.
It does not necessarily free up the memory,which depends on when the garbage collector runs(which depends on JVM).
When the garbage collector runs,it frees up the heap by deleting only the objects which are eligible for garbage collection.
It is a good to have. When you set objects to null, there is a possibility that the object can be garbage collected faster, in the immediate GC cycle. But there is no guaranteed mechanism to make an object garbage collected at a given time.

Exceptions in constructors

In C++, the lifetime of an object begins when the constructor finishes successfully. Inside the constructor, the object does not exist yet.
Q: What does emitting an exception from a constructor mean?
A: It means that construction has failed, the object never existed, its lifetime never began. [source]
My question is: Does the same hold true for Java? What happens, for example, if I hand this to another object, and then my constructor fails?
Foo()
{
Bar.remember(this);
throw new IllegalStateException();
}
Is this well-defined? Does Bar now have a reference to a non-object?
The object exists, but it's not been initialized properly.
This can happen whenever this leaks during construction (not just when you throw an exception).
It's a very problematic situation, because some commonly assumed guarantees don't hold true in this situation (for example final fields could seem to change their value during construction).
Therefore you should definitely avoid leaking this in the constructor.
This IBM developerWorks article describes the precautions to take when constructing objects and the reasoning behind those precautions. While the article discusses the subject in the light of multi-threading, you can have similar problems in a single-threaded environment when unknown/untrusted code gets a reference to this during construction.
You should never open resources like a file writer in your constructor. Create a init method instead and do it from there. Then you're safe.
This code is not exception safe and neither would be exception safe in C++. It's same bug regardless of the language you use.

Categories

Resources