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.
I'm surprised at how it is possible to continue execution even after a StackOverflowError has occurred in Java.
I know that StackOverflowError is a sublass of the class Error.
The class Error is decumented as "a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch."
This sounds more like a recommendation than a rule, subtending that catching a Error like a StackOverflowError is in fact permitted and it's up to the programmer's reasonability not to do so. And see, I tested this code and it terminates normally.
public class Test
{
public static void main(String[] args)
{
try {
foo();
} catch (StackOverflowError e) {
bar();
}
System.out.println("normal termination");
}
private static void foo() {
System.out.println("foo");
foo();
}
private static void bar() {
System.out.println("bar");
}
}
How can this be? I think by the time the StackOverflowError is thrown, the stack should be so full that there is no room for calling another function. Is the error handling block running in a different stack, or what is going on here?
When the stack overflows and StackOverflowError is thrown, the usual exception handling unwinds the stack. Unwinding the stack means:
abort the execution of the currently active function
delete its stack frame, proceed with the calling function
abort the execution of the caller
delete its stack frame, proceed with the calling function
and so on...
... until the exception is caught. This is normal (in fact, necessary) and independent of which exception is thrown and why. Since you catch the exception outside of the first call to foo(), the thousands of foo stack frames that filled the stack have all been unwound and most of the stack is free to be used again.
When the StackOverflowError is thrown, the stack is full. However, when it's caught, all those foo calls have been popped from the stack. bar can run normally because the stack is no longer overflowing with foos. (Note that I don't think the JLS guarantees you can recover from a stack overflow like this.)
When the StackOverFlow occurs, the JVM will pop down to the catch, freeing the stack.
In you example, it get rids of all the stacked foo.
Because the stack doesn't actually overflow. A better name might be AttemptToOverflowStack. Basically what it means is that the last attempt to adjust the stack frame errs because there isn't enough free space left on the stack. The stack could actually have lots of space left, just not enough space. So, whatever operation would have depended upon the call succeeding (typically a method invocation), never gets exectued and all that is left is for the program to deal with that fact. Which means that it is really no different from any other exception. In fact, you could catch the exception in the function that is making the call.
As has already been answered, it is possible to execute code, and in particular to call functions, after catching a StackOverflowError because the normal exception handling procedure of the JVM unwinds the stack between the throw and the catch points, freeing stack-space for you to use. And your experiment confirms that is the case.
However, that is not quite the same as saying that it is, in general, possible to recover from a StackOverflowError.
A StackOverflowError IS-A VirtualMachineError, which IS-AN Error. As you point out, Java provides some vague advice for an Error:
indicates serious problems that a reasonable application should not try to catch
and you, reasonably, conclude that should sounds like catching an Error might be OK in some circumstances. Note that performing one experiment does not demonstrate that something is, in general, safe to do. Only the rules of the Java language and the specifications of the classes you use can do that. A VirtualMachineError is a special class of exception, because the Java Language Specification and the Java Virtual Machine Specification provide information about the semantics of this exception. In particular, the latter says:
A Java Virtual Machine implementation throws an object that is an instance of a subclass of the class VirtualMethodError when an internal error or resource limitation prevents it from implementing the semantics described in this chapter. This specification cannot predict where internal errors or resource limitations may be encountered and does not mandate precisely when they can be reported. Thus, any of the VirtualMethodError subclasses defined below may be thrown at any time during the operation of the Java Virtual Machine:
...
StackOverflowError: The Java Virtual Machine implementation has run out of stack space for a thread, typically because the thread is doing an unbounded number of recursive invocations as a result of a fault in the executing program.
The crucial problem is that you "cannot predict" where or when a StackOverflowError will be thrown. There are no guarantees about where it will not be thrown. You can not rely on it being thrown on entry to a method, for example. It could be thrown at a point within a method.
This unpredictability is potentially disastrous. As it can be thrown within a method, it could be thrown part way through a sequence of operations that the class considers to be one "atomic" operation, leaving the object in a partially modified, inconsistent, state. With the object in an inconsistent state, any attempt to use that object could result in erroneous behaviour. In all practical cases you can not know which object is in an inconsistent state, so you have to assume that no objects are trustworthy. Any recovery operation or attempt to continue after the exception is caught could therefore have erroneous behaviour. The only safe thing to do is therefore to not catch a StackOverflowError, but rather to allow the program to terminate. (In practice you might attempt to do some error logging to assist troubleshooting, but you can not rely on that logging operating correctly). That is, you can not reliably recover from a StackOverflowError.
Suppose you have created an instance of a Window class. The window is shown to the user. Then, an exception is thrown, and reference to the instance is lost, but the window is still seen by the user because the instance still exists (it's just not referenced anymore).
What to do in these circumstances?
I'm specifically talking about the Squirrel scripting language (http://www.squirrel-lang.org/). Contrary to Java, it doesn't seem to have finally blocks or finalizer methods, so is exception handling broken in this language?
I don't know squirrel, but even in the absence of a finally block you could simulate the behaviour to some extent within Java:
Exception error = null;
try {
// do something
}
catch (Exception e) {
error = e;
}
// My finally code goes here
// ...
if (error != null) {
// Oh dear clean up all my resources - files, windows, sockets etc.
throw error;
}
So the catch block stores the exception in a variable that you can test later if you want to rethrow it, and it still allows you the chance to do other cleanup. Obviously there are nuances that you have to be aware of (e.g. explicit kinds of exception that need special handling, more exceptions being thrown outside the try / catch) but with careful consideration you should be okay.
System resources (like graphics handles, sockets, windows, file handles etc.) in particular tend to be a bit messy in Java and other garbage collected languages. Usually these resources will be managed by a class with an explicit close() method. So if you know things have fallen in a heap you would normally invoke an explicit close() on the objects to clean them up straightaway. Otherwise the object will cleanup itself during finalization but only during GC which could be a long time coming.
I have written a class which loads configuration objects of my application and keeps track of them so that I can easily write out changes or reload the whole configuration at once with a single method call. However, each configuration object might potentially throw an exception when doing IO, yet I do not want those errors to cancel the overall process in order to give the other objects still a chance to reload/write. Therefore I collect all exceptions which are thrown while iterating over the objects and store them in a super-exception, which is thrown after the loop, since each exception must still be handled and someone has to be notified of what exactly went wrong. However, that approach looks a bit odd to me. Someone out there with a cleaner solution?
Here is some code of the mentioned class:
public synchronized void store() throws MultipleCauseException
{
MultipleCauseException me = new MultipleCauseException("unable to store some resources");
for(Resource resource : this.resources.values())
{
try
{
resource.store();
}
catch(StoreException e)
{
me.addCause(e);
}
}
if(me.hasCauses())
throw me;
}
If you want to keep the results of the operations, which it seems you do as you purposely carry on, then throwing an exception is the wrong thing to do. Generally you should aim not to disturb anything if you throw an exception.
What I suggest is passing the exceptions, or data derived from them, to an error handling callback as you go along.
public interface StoreExceptionHandler {
void handle(StoreException exc);
}
public synchronized void store(StoreExceptionHandler excHandler) {
for (Resource resource : this.resources.values()) {
try {
resource.store();
} catch (StoreException exc) {
excHandler.handle(exc);
}
}
/* ... return normally ... */
]
There are guiding principles in designing what and when exceptions should be thrown, and the two relevant ones for this scenario are:
Throw exceptions appropriate to the abstraction (i.e. the exception translation paradigm)
Throw exceptions early if possible
The way you translate StoreException to MultipleCauseException seems reasonable to me, although lumping different types of exception into one may not be the best idea. Unfortunately Java doesn't support generic Throwables, so perhaps the only alternative is to create a separate MultipleStoreException subclass instead.
With regards to throwing exceptions as early as possible (which you're NOT doing), I will say that it's okay to bend the rule in certain cases. I feel like the danger of delaying a throw is when exceptional situations nest into a chain reaction unnecessarily. Whenever possible, you want to avoid this and localize the exception to the smallest scope possible.
In your case, if it makes sense to conceptually think of storing of resources as multiple independent tasks, then it may be okay to "batch process" the exception the way you did. In other situations where the tasks has more complicated interdependency relationship, however, lumping it all together will make the task of analyzing the exceptions harder.
In a more abstract sense, in graph theory terms, I think it's okay to merge a node with multiple childless children into one. It's probably not okay to merge a whole big subtree, or even worse, a cyclic graph, into one node.
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.