The try-with-resources - java

I have a very simple question that seems to be stupid to me but yet asking .How BufferedReader call the close() method of Autocloseable interface. or how we can implement Autocloseable that call the close() automatically.

It's syntactic sugar. The javac compiler inserts the close() call into the compiled class at the end of the try block where the BufferedReader is declared, as you can see if you disassemble the class file with javap -c.

There's nothing you have to do in your own code besides implement AutoCloseable and provide a close() method. Java takes care of calling for you the close() method at the end of the try statement. Consider the following minimal demonstration:
class MyCloseable implements AutoCloseable {
public void close() { System.out.println("Close was called"); }
}
public class Ac {
public static void main(String[] args) {
try (MyCloseable mc = new MyCloseable()) {
}
}
}
$ java Ac
Close was called

try(AutoClosable x = open()) {}
is usually seen as short-hand version of
try {
Resource x = open();
} finally {
x.close();
}
There are two actual differences :
If both blocks throw, the autoclosable try statement will throw the exception from within the try statement, whereas the try...finally will throw the exception from the finally block. An exception from the other block would be suppressed.
In addition the exact behaviour is like this:
try(Autoclosable x = open) {
//do something
} do_close {
x.close();//not actually there - executed before catch and finally!
} catch (WhateverException e){
//catch an exception
} finally {
//finally do something
}
From the Oracle Docs:
"A try-with-resources statement can have catch and finally blocks just
like an ordinary try statement. In a try-with-resources statement, any
catch or finally block is run after the resources declared have been
closed."
So due to these two technical details it is not just syntactic sugar, but in practice it is used where formerly try...finally would have been used.
There is no actual way to imitate the behavior of try-with-resources for other interfaces than Autoclosable afaik. If you want to do some cleanup after a try you will have to either use finally or implement Autoclosable. Finalizers seem to do something similar, but actually they don't. I just mention them here to advise you not to use them.

Related

use try-with-resources to close a Closeable

I have a Map<Key, Closeable> and if a key is removed from the map I want to close the Closeable. Normally I have something like:
Closeable c = map.remove(key);
c.close();
My Eclipse warns me "Resource 'c' should be managed by try-with-resource", so is it better just to write the following?
try (Closeable c = map.remove(key)) {}
In my special implementation I have a subclass of Closeable, where close() does not throw an IOException, so no exception handling is needed.
The point of try-with-resources is that:
The opening of the Closeable resource is done in the try statement
The use of the resource is inside the try statement's block
close() is called for you automatically.
So your suggested code:
try(Closeable c = map.remove(key)) {}
... doesn't satisfy the point of try-with-resource, since you're not using the resource inside the block. Presumably your Closeable is already open before this statement.
I'm guessing that you have some code whereby a bunch of resources are opened, work is done, then they are all closed by working through the map.
This is OK, and sometimes unavoidable. But it's cleaner, where possible, to have open() and close() in the same method, with the close() in a finally block, so that you can see at a glance that every open() has a corresponding close() and you can be sure that the close() is always called.
MyCloseable c = MyCloseable.open(...);
try{
// do stuff with c;
} finally {
try {
c.close();
} catch (IOException e) {
// ...
}
}
Once you've achieved that, try-with-resources just makes things neater:
try(MyCloseable c = MyCloseable.open(...)) {
// do stuff with c;
}
If your requirements mean you can't get open and close into the same methods, then just stick with an explicit close() and ignore the warning.
I would just ignore this warning, If you are managing close operation on your own, then just call close(). Empty try-with-resource looks weird.
Consider to extend Map so close operation will be performed automatically on remove:
public class CloseableMap<K,V extends Closeable> extends HashMap<K,V> {
#Override
public R remove(K key) {
V resource = super.remove(key);
if (resource != null) {
resource.close();
}
return resource;
}
}

What's the use of finally block in try with resources(Java 7)?

The finally block is mainly used to prevent resource leaks which can be achieved in close() method of resource class. What's the use of finally block with try-with-resources statement, e.g:
class MultipleResources {
class Lamb implements AutoCloseable {
public void close() throws Exception {
System.out.print("l");
}
}
class Goat implements AutoCloseable {
public void close() throws Exception {
System.out.print("g");
}
}
public static void main(String[] args) throws Exception {
new MultipleResources().run();
}
public void run() throws Exception {
try (Lamb l = new Lamb(); Goat g = new Goat();) {
System.out.print("2");
} finally {
System.out.print("f");
}
}
}
Ref: K.Seirra, B. Bates OCPJP Book
Just like in regular try-catch-finally block - finally block is used when you want something to always happen, no matter if operation in try block succeeds or not.
I think your question is about providing some use-case when it is really useful. Try to imagine a situation when you have to tell one collabolator (or publish an event) that your processing is finished - regardless of its result. You can then put in the finally block the code which is resposible for announcing the finishing of processing.
Plase note that when some operation in try-with-resources block without catch throws an exception, the code following that block will not be executed.
The code in finally block with always get executed unless the thread that executing the code or the JVM is terminated.
This ensures that any resources you allocated will get cleaned up in the finally regardless.
The Java doc has a detail explanation of finally.

try-with-resources fails to call close()

I am using the handy try-with-resources statement to close connections. This works great in most cases but only in one utterly simple method it does not work properly. Namely, here:
public boolean testConnection(SapConnection connection) {
SapConnect connect = createConnection(connection);
try ( SapApi sapApi = connect.connect() ) {
return ( sapApi != null );
} catch (JCoException e) {
throw new UncheckedConnectionException("...", e);
}
}
The sapApi object is non-null, the method returns true, but the close() method of sapApi is never called. I now resorted to use a finally block which works fine. But this is quite puzzling. The Java byte code also contains a call to close. Has anyone seen this behavior before?
Edit to clarify the situation:
This is the SapApi, it implements AutoCloseable, of course.
class SapApi implements AutoCloseable {
#Override
public void close() throws JCoException {
connection.close(); // this line is not hit when leaving testConnection(..)
}
..
}
The following is another method in the same class as testConnection(..). Here SapApi.close() is called before returning.
#Override
public List<Characteristic> selectCharacteristics(SapConnect aConnection, InfoProvider aInfoProvider) {
try (SapApi sapi = aConnection.connect()) {
return sapi.getCharacteristics(aInfoProvider);
} catch ( Exception e ) {
throw new UncheckedConnectionException(e.getMessage(), e);
}
}
Edit 2:
This is SapConnect.connect():
SapApi connect() {
try {
... // some setup of the connection
return new SapApi(this); // single return statement
} catch (Exception e) {
throw new RuntimeException(e);
}
}
SapApi has no subclasses. There is just one implementation with the close method as above. In particular, there is no empty close().
In order for close() to be called, SapApi must implement AutoCloseable interface, but since we are talking about connection, it is more appropriate that you SapApi will implement Closable interface which throws IOException.
Read this:
http://tutorials.jenkov.com/java-exception-handling/try-with-resources.html
I do not know what you mean by
This works great in most cases
1 That normally the SapApi is closed when used in try-with-resources
or
2 That it normally works for resources other than SapApi
I am answering on the assumption of number 2.
Try-with-resources will only work in Java 7 for resources that implement the AutoCloseable interface. So my first advice would be to for you to check the API for SapConnect and SapApi (whatever they are) to determine if that is the case.
One guess: maybe connect returns a child or proxy class of SapApi. With close overridden to do nothing if no change was made, only otherwise call super.close().
I'll give it as an answer, as AutoCloseable works even if no method is called.

Why is try-with-resources catch block selectively optional?

I read that the catch block in try-with-resources is optional.
I've tried creating a Connection object in a try-with-resources block, with no subsequent catch block, only to get compiler error from eclipse:
"Unhandled exception type SQLException thrown by automatic close() invocation."
Since every resource that can be used in try-with-resources implements AutoCloseable, and so potentially throws an exception upon invocation of the close() method, I don't understand how the catch clause is optional, given that it's not allowing me to skip catching the exception from close().
Is there some special requirement that the specific implementation of AutoCloseable not directly declare any exception thrown in its close() method? (e.g. override AutoCloseable's close() throws Exception with a close() which does not throw any Exception)?
..or is this possibly just an eclipse issue?
Edit: Here's the simplest code fragment that still triggers the problem:
try (Connection con = dataSource.getConnection()) {
/*...*/
}
Thoughts on whether or not this is related to the use of a JNDI DataSource?
Thanks in advance.
It is optional if close() is not able to throw a checked exception. However, if close() can, then a checked exception would need to handled in a normal fashion, either with a catch block, or by throwing from the method that try-with-resources block is in.
More details are in JLS 14.2.3
14.20.3.2. Extended try-with-resources
A try-with-resources statement with at least one catch clause and/or a finally clause is called an extended try-with-resources statement.
The meaning of an extended try-with-resources statement:
try ResourceSpecification
Block
[Catches]
[Finally]
is given by the following translation to a basic try-with-resources statement nested inside a try-catch or try-finally or try-catch-finally statement:
try {
try ResourceSpecification
Block
}
[Catches]
[Finally]
The effect of the translation is to put the resource specification "inside" the try statement. This allows a catch clause of an extended try-with-resources statement to catch an exception due to the automatic initialization or closing of any resource.
Furthermore, all resources will have been closed (or attempted to be closed) by the time the finally block is executed, in keeping with the intent of the finally keyword.
Thoughts on whether or not this is related to the use of a JNDI DataSource?
Yes, it is.
In the example try-with-resourses block you've provided, it is necessary to catch the exception and handle, or throw from the method the block is in, because SQLException is a checked exception.
You could just be throwing the exception up (or catching it in another try-catch block):
private static void test() throws IOException {
try(InputStream is = new FileInputStream("test.txt")) {
while(is.read() > -1) {
}
} finally {
// Will get executed, even if exception occurs
System.out.println("Finished");
}
}
You can create an AutoClosable that does not require an explicit catch-block by declaring your AutoClosable's close() method without any Exception or with a RuntimeException. Without any Exception it is clear that no catch-block is required. Further, the compiler does not statically check for a RuntimeException to be catched (in contrast to checked Exceptions).
Example:
public class AutoClosableDemo
{
public static void main( final String[] args )
{
try (MyAutoCloseable1 mac1 = new MyAutoCloseable1())
{
System.out.println( "try-with-resource MyAutoCloseable1" );
}
try (MyAutoCloseable2 mac2 = new MyAutoCloseable2())
{
System.out.println( "try-with-resource MyAutoCloseable2" );
}
// The following is not allowed, because
// "Unhandled exception type Exception thrown by automatic close() invocation on mac3"
// try (MyAutoCloseable3 mac3 = new MyAutoCloseable3())
// {
// System.out.println( "try-with-resource MyAutoCloseable13" );
// }
System.out.println( "done" );
}
public static class MyAutoCloseable1 implements AutoCloseable
{
#Override
public void close()
{
System.out.println( "MyAutoCloseable1.close()" );
}
}
public static class MyAutoCloseable2 implements AutoCloseable
{
#Override
public void close() throws RuntimeException
{
System.out.println( "MyAutoCloseable2.close()" );
}
}
public static class MyAutoCloseable3 implements AutoCloseable
{
#Override
public void close() throws Exception
{
System.out.println( "MyAutoCloseable3.close()" );
}
}
}
You could check the JLS but there is actually a relatively easy reasoning why this is the only correct way the language should behave.
The main rule of checked exceptions is that any checked exception declared by a method must be handled, either by catching it or letting the calling method throw it.
The try-with-resources always (implicitly) calls the close method.
So if the specific close method of the AutoClosable you use (determined by the type declared in try) declares to throw a checked exception such as a SQLException you do need to handle this checked exception somewhere, otherwise it would be possible to violate the rule!
If the close method does not declare that it throws a checked exception, the rule is not violated and you do not need to handle a checked exception for implicitly calling the close method. It is actually a compilation failure if you do try to catch a checked exception that is never declared to be thrown.
Not every Java class (!) throws an exception. Sometimes you just want to use a try-with-resources to use the auto-close feature, and nothing else.
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
This the catch is optional because readLine() doesn't throw a (checked) exception.
Yes, close() could throw an exception, but the try-with-resources handles that too.
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
So this try-with-resources doesn't need a catch.

implements Closeable or implements AutoCloseable

I'm in the process of learning Java and I cannot find any good explanation on the implements Closeable and the implements AutoCloseable interfaces.
When I implemented an interface Closeable, my Eclipse IDE created a method public void close() throws IOException.
I can close the stream using pw.close(); without the interface. But, I cannot understand how I can implement theclose() method using the interface. And, what is the purpose of this interface?
Also I would like to know: how can I check if IOstream was really closed?
I was using the basic code below
import java.io.*;
public class IOtest implements AutoCloseable {
public static void main(String[] args) throws IOException {
File file = new File("C:\\test.txt");
PrintWriter pw = new PrintWriter(file);
System.out.println("file has been created");
pw.println("file has been created");
}
#Override
public void close() throws IOException {
}
AutoCloseable (introduced in Java 7) makes it possible to use the try-with-resources idiom:
public class MyResource implements AutoCloseable {
public void close() throws Exception {
System.out.println("Closing!");
}
}
Now you can say:
try (MyResource res = new MyResource()) {
// use resource here
}
and JVM will call close() automatically for you.
Closeable is an older interface. For some reason To preserve backward compatibility, language designers decided to create a separate one. This allows not only all Closeable classes (like streams throwing IOException) to be used in try-with-resources, but also allows throwing more general checked exceptions from close().
When in doubt, use AutoCloseable, users of your class will be grateful.
Closeable extends AutoCloseable, and is specifically dedicated to IO streams: it throws IOException instead of Exception, and is idempotent, whereas AutoCloseable doesn't provide this guarantee.
This is all explained in the javadoc of both interfaces.
Implementing AutoCloseable (or Closeable) allows a class to be used as a resource of the try-with-resources construct introduced in Java 7, which allows closing such resources automatically at the end of a block, without having to add a finally block which closes the resource explicitly.
Your class doesn't represent a closeable resource, and there's absolutely no point in implementing this interface: an IOTest can't be closed. It shouldn't even be possible to instantiate it, since it doesn't have any instance method. Remember that implementing an interface means that there is a is-a relationship between the class and the interface. You have no such relationship here.
It seems to me that you are not very familiar with interfaces. In the code you have posted, you don't need to implement AutoCloseable.
You only have to (or should) implement Closeable or AutoCloseable if you are about to implement your own PrintWriter, which handles files or any other resources which needs to be closed.
In your implementation, it is enough to call pw.close(). You should do this in a finally block:
PrintWriter pw = null;
try {
File file = new File("C:\\test.txt");
pw = new PrintWriter(file);
} catch (IOException e) {
System.out.println("bad things happen");
} finally {
if (pw != null) {
try {
pw.close();
} catch (IOException e) {
}
}
}
The code above is Java 6 related. In Java 7 this can be done more elegantly (see this answer).
Here is the small example
public class TryWithResource {
public static void main(String[] args) {
try (TestMe r = new TestMe()) {
r.generalTest();
} catch(Exception e) {
System.out.println("From Exception Block");
} finally {
System.out.println("From Final Block");
}
}
}
public class TestMe implements AutoCloseable {
#Override
public void close() throws Exception {
System.out.println(" From Close - AutoCloseable ");
}
public void generalTest() {
System.out.println(" GeneralTest ");
}
}
Here is the output:
GeneralTest
From Close - AutoCloseable
From Final Block
Recently I have read a Java SE 8 Programmer Guide ii Book.
I found something about the difference between AutoCloseable vs Closeable.
The AutoCloseable interface was introduced in Java 7. Before that, another interface
existed called Closeable. It was similar to what the language designers wanted, with the
following exceptions:
Closeable restricts the type of exception thrown to IOException.
Closeable requires implementations to be idempotent.
The language designers emphasize backward compatibility. Since changing the existing
interface was undesirable, they made a new one called AutoCloseable. This new
interface is less strict than Closeable. Since Closeable meets the requirements for
AutoCloseable, it started implementing AutoCloseable when the latter was introduced.
The try-with-resources Statement.
The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Please refer to the docs.

Categories