Java applications may use IO streams, sockets or database connections that should be closed when they are no longer needed.
However, applications may be terminated (e.g. by killing the process). Will all used resources be freed in this case? Who will free them: OS or JRE?
The JVM will release all active resources upon termination; however, this does not ensure that the other end will free the resource too, so explicitly closing resources is in every programmer's best interest.
An alternative to explicitly closing streams exists in Java 7, called the try-resource "statement", which is the equivalent of closing a resource in a finally block after a try block. More info on that can be found here.
If your software doesn't take care of resource management properly, the following will happen:
at runtime: the JVM will attempt during the duration of your program to close open streams if they're are seemingly unused (during garbage collection cycles),
at your program's termination point: the JVM should close open streams of all kinds left open by your program,
at the JVM's process termination point: the operating system will take care of releasing anything that hasn't been properly released by the JVM when it exists (hopefully, or this OS has some serious issues...).
As mentioned by Vulcan, none of this ensures that they are properly dealt with on the other end, obviously.
Note that the 3rd bullet point is a rather generic thing: most operating systems will take care of this, and it doesn't relate to the Java Platform's internals. It's about the OS managing its processes and resources on its own.
More Info
See also:
Cleanup of resources on an abnormal Exit, also on StackOverflow
How do I implement graceful termination in Java
Java Theory and Practice: Good Housekeeping Practices, at the IBM Developer Series
Related
What is the meaning of the word "resource" in java?
Why we have to close it after usage,even though garbage collector runs in jvm ?
Why we have to write resource cleanup code in finally block?
A resource is something that has a limited ammount, such as DB connections and file descriptors. The GC frees memory, but you still have to release resources such as DB connections, open files, etc..., to allow other threads to use them.
By the way, it's better to free the resources immediately after you finish using them, and not just in the finalize method, which might take a long time until it is called by the GC.
A database connection, a thread, a file handle, a socket - all are finite resources.
The operating system you run on only allows so many threads - 1 MB overhead per thread. You're limited by the available RAM. Same for file handles and sockets.
Database connections are interesting because they involve client and server. If the client gc's the connection, what tells the server to close the connection? If you fail to close in finally blocks, you'll soon find out that your database server will run out of connections under heavy load.
Finalize is not the right way to go. Don't depend on the VM to call it. Write a close() method and call it in a finally block when your method is done with the resource. Close in the narrowest scope possible.
Say you have a file, you can write to it and not close the resource and eventually it will be closed by the GC. The problem is that while the file is open you can't delete it in windows, and in Linux you can delete it but it doesn't free any space. If you want to delete a file you don't want to be waiting until the GC feels like running perhaps hours later.
What is the meaning of the word "resource" in java?
The typical Java application manipulates several types of resources such as files, streams, sockets, and database connections.
Why we have to write resource cleanup code in finally block?
The Oracle article presents the Java 7 answer to the automatic resource management problem.
Such resources must be handled with great care, because they acquire system resources for their operations. Thus, you need to ensure that they get freed even in case of errors.
Indeed, incorrect resource management is a common source of failures in production applications, with the usual pitfalls being database connections and file descriptors remaining opened after an exception has occurred somewhere else in the code.
This leads to application servers being frequently restarted when resource exhaustion occurs, because operating systems and server applications generally have an upper-bound limit for resources.
Use Java 7 The try-with-resources Statement
To use exit(0) in C is not a good practice, if there are alternatives, since it does not free resources for example. But to use System.exit(0) in Java - how is it here? Could one trust the garbage collector in this context?
C language:
exit(0);
Java:
System.exit(0)
But to use System.exit(0) in java - how is it here? Could one trust the garbage-collector in this context?
When you call System.exit in Java, the garbage collector is not normally run1. However, in any JVM that I've ever heard of, there is something else that reclaims all of the objects that were allocated. (Typically it is handled at the operating system level.)
The fact that the GC doesn't run is only significant if you are relying on object finalizers to so something important before the JVM terminates.
Hypothetically, if your Java application used JNI (etc) to call native methods, then those methods could access system resources that might be problematic. However:
As a general rule the operating system does take care of such things. At least it does for modern versions of Linux and UNIX, AFAIK.
The garbage collector has no knowledge of those resources anyway. If the OS can't reclaim them, then the Java garbage collector won't help.
If you did need to clean up such resources acquired by a Java program (via native code) then the best approach would be to implement the cleanup in native code methods, and use a "shutdown hook" to run them. The shutdown hooks will be run if you call System.exit.
1 - A garbage collection will be performed on JVM exit if you have previously called runFinalizersOnExit(true). However, this is a deprecated method. The Oracle site explains it like this:
Q: Why is Runtime.runFinalizersOnExit deprecated?
A: Because it is inherently unsafe. It may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock. While this problem could be prevented if the class whose objects are being finalized were coded to "defend against" this call, most programmers do not defend against it. They assume that an object is dead at the time that its finalizer is called.
Further, the call is not "thread-safe" in the sense that it sets a VM-global flag. This forces every class with a finalizer to defend against the finalization of live objects!
In short, this is a dangerous approach, and it won't directly deal with the kind of resources that the OP is worried about.
Think of it like this. In C, you are building your source code into a binary file that will execute on it's own only conforming to the rules of logical programming and the rules set by your OS. The OS however does not manage your memory for you. It handles events and sends information to the hardware that tell it how to run, nothing more, nothing less. In java, all code is compiled into java's own bytecode. Upon execution it does not actually at any time communicate to the OS. The virtual machine designed to run that bytecode is what does the talking. When you call System.exit (0), you are telling the virtual machine that the app you are running is coming to a halt, from there the machine handles IT'S OWN MEMORY which just so happens to include anything you did not already remove via the garbage collector but only if the VM is exiting as well. Hope that helps
I've always heard that resources in java must be closed after use or these resources will get exhausted. Is it really a matter of concern for small programs that use very few resources(like 1 or 2 file readers/ buffered readers and all)? Doesn't the JVM keep track of the resources being used by a program? And wouldn't it release all those resources once the program exits? If not, why would the JVM keep these resources blocked even after the program exit?
These resources are indeed closed upon a normal JVM exit. However, you may not always know how your method is being called, and it could perhaps be called 2000 times externally by another programmer, and those resources will start to stack up.
In addition, certain non-mainstream OSs may run into the issue that if the JVM were to halt abnormally(via Runtime.getRuntime().halt() or a significant internal error/inconsistency within the JVM) then resources could remain open(due to cleanup code not being run), potentially unusable until rebooted or manually released. Even on mainstream systems sockets could remain open for multiple minutes.
When the process exits, the JVM exits. What happens then is that the OS will free up any resources previously used by the JVM. This includes things like memory, file handles etc.
Small programms might live with resource leaks, because the OS might handle this after the process ended. But this is considered non portable.
The bigger issue is that the OS the JVM is running in won't know how to free resources allocated on a remote machine or if there are even resources allocated that need to be freed.
It is not JVM but OS who releases resources allocated to the JVM process after it exited.
A quote from Effective Java states that:
A second legitimate use of finalizers concerns objects with native peers. A
native peer is a native object to which a normal object delegates via native methods. Because a native peer is not a normal object, the garbage collector doesn’t
know about it and can’t reclaim it when its Java peer is reclaimed. A finalizer is an
appropriate vehicle for performing this task, assuming the native peer holds no
critical resources.
I've not done C++ before, though I'm vaguely aware that file handlers and database connections are critical resources. But what exactly does it mean for a resource to be non-critical?
Or rather, what are some examples of non-critical resources?
“Non-critical resources” don’t exist. The quote isn’t talking about non-critical resources, it’s merely talking about the absence of critical resources.
In a way, you could say that memory is a non-critical resource in a garbage-collected system. However, I’m not convinced that this would be correct (quite the opposite, in fact: managed resources can still be critical if they run out), and I’ve never heard this being said.
I don't think it's really the resource that's critical, despite the phrase used. I think it's recovering the resource that may or may not be critical, and the quote could be rephrased, "assuming it is not critical that the resource is freed".
If it's critical that the resource is freed by a particular point in program execution, after the object is unreachable but before the resource is needed for some other purpose, then a finalizer is inadequate. Instead you need some program logic to make sure it happens.
So, file handles or db connections are critical if you're worried that you might run out, they're not critical otherwise. If you've reached some limit of open DB connections, because the finalizers that would close your old ones haven't been run yet, and you try to open another DB connection, chances are it'll fail. The situation with memory is rather better, since if you've run out of memory because of unreachable objects, and try to create a new object, then the GC will at least make an effort to find something to finalize and free.
Thus, file handles and db connections should have a close() function that the user can call to free all resources in cases where the program logic is able to determine that the object will not be used again. Expecting the GC to close the connection via a finalizer isn't reliable enough. It also doesn't deal well with the possibility of a flush or commit failing, although that's a separate issue.
This question already has answers here:
Why would you ever implement finalize()?
(21 answers)
Closed 5 years ago.
This is mostly out of curiosity.
I was wandering if anyone has encountered any good usage for Object.finalize() except for debugging/logging/profiling purposes ?
If you haven't encountered any what would you say a good usage would be ?
If your Java object uses JNI to instruct native code to allocate native memory, you need to use finalize to make sure it gets freed.
Late to the party here but thought I would still chime in:
One of the best uses I have found for finalizers is to call explicit termination methods which, for what ever reason, were not called. When this occurs, we also log the issue because it is a BUG!
Because:
There is no guarantee that finalizers will be executed promptly (or technically at all), per the language specification
Execution is largely dependent on the JVM implementation
Execution can sometimes be delayed if the GC has a lower thread priority
This leaves only a handful of tasks that they can address without much risk.
close external connections (db, socket etc)
close open files. may be even try to write some additional information.
logging
if this class runs external processes that should exist only while object exists you can try to kill them here.
But it is just a fallback that is used is "normal" mechanism did not work. Normal mechanism should be initiated explicitly.
Release resources that should be released manually in normal circumstances, but were not released for some reason. Perhaps with write a warning to the log.
I use it to write back data to a database when using soft references for caching database-backed objects.
I see one good use for finalize(): freeing resources that are available in large amounts and are not exclusive.
For example, by default there are 1024 file handles available for a Linux process and about 10000 for Windows. This is pretty much, so for most applications if you open a file, you don't have to call .close() (and use the ugly try...finally blocks), and you'll be OK - finally() will free it for you some time later. However for some pieces of code (like intensive server applications), releasing resources with .close() is a must, otherwise finally() may be called too late for you and you may run out of file handles.
The same technique is used by Swing - operating system resources for displaying windows and drawing aren't released by any .close() method, but just by finalize(), so you don't have to worry about all .close() or .dispose() methods like in SWT for example.
However, when there is very limited number of resources, or you must 'lock' resource to use it, also remember to 'unlock' it. For example if you create a file lock on a file, remember also to remove this lock, otherwise nobody else will be able to read or write this file and this can lead to deadlocks - then you can't rely on finalize() to remove this lock for you - you must do it manually at the right place.