Which close() runs first? - java

If I have multiple resources, in a try catch, which one gets closed called on first?
public class TestRes {
public static void main(String[] args) {
TestRes tr = new TestRes();
tr.test();
}
public void test() {
try (MyResource1 r1 = new MyResource1(); MyResource2 r2 = new MyResource2(); ) {
System.out.print("T ");
} catch (IOException ioe) {
System.out.print("IOE ");
} finally {
System.out.print("F ");
}
}
class MyResource1 implements AutoCloseable {
public void close() throws IOException {
System.out.print("1 ");
}
}
class MyResource2 implements Closeable {
public void close() throws IOException {
throw new IOException();
}
}
}
This sample outputs:
T 1 IOE F
If I change the order so...
public class TestRes {
public static void main(String[] args) {
TestRes tr = new TestRes();
tr.test();
}
public void test() {
try (MyResource2 r2 = new MyResource2(); MyResource1 r1 = new MyResource1();) {
System.out.print("T ");
} catch (IOException ioe) {
System.out.print("IOE ");
} finally {
System.out.print("F ");
}
}
class MyResource1 implements AutoCloseable {
public void close() throws IOException {
System.out.print("1 ");
}
}
class MyResource2 implements Closeable {
public void close() throws IOException {
throw new IOException();
}
}
}
I get the same output - why?

It seems that you believe an exception from a close() method will prevent other close() methods from being called. That is wrong.
The Java Language Specification, section 14.20.3. try-with-resources, says:
Resources are closed in the reverse order from that in which they were initialized. A resource is closed only if it initialized to a non-null value. An exception from the closing of one resource does not prevent the closing of other resources. Such an exception is suppressed if an exception was thrown previously by an initializer, the try block, or the closing of a resource.
Which means that the close() method printing 1 will always be executed, and the first part answers your "Which close() runs first?" question.

Related

Multiple threads loading different classes using Class.forName("...")

I have a scenario in which I thread should monitor Clickhouse and the other one should sqlite. In order to load driver classes, I am using Class.forName("..."). Since the threads are starting at a time. I think it is going under deadlock situation..
Here is the piece of code that describes the issue.
public class ch {
public static void main(String[] args) throws Exception {
new OTTLCleaner().start(); // loading CH Driver
new CHThr().start(); // loading CH Driver
Spark.getInstance(); // loading Sqlite Driver
}
}
class OTTLCleaner extends Thread {
#Override
public void run() {
try {
System.out.println("Inside OTTL");
DBHelper.deleteTables();
...
} catch (Exception e) {
System.out.println(e);
}
}
}
class CHThr extends Thread {
#Override
public void run() {
try {
System.out.println("Inside CHThr");
DBHelper.CHConn();
...
} catch (Exception e) {
System.out.println(e);
}
}
}
class Spark implements Runnable {
private static class SingletonHelper {
private static final Spark INSTANCE = new Spark();
}
public static Spark getInstance() {
return SingletonHelper.INSTANCE;
}
private Spark() {
try {
System.out.println("Inside Spark");
DBHelper.SqliteConn();
...
} catch (Exception e) {
System.out.println(e);
}
}
#Override
public void run() {
...
}
}
class DBHelper {
public static void CHConn() throws ClassNotFoundException, SQLException {
Class.forName("ru.yandex.clickhouse.ClickHouseDriver");
System.out.println("CH");
...
}
static synchronized void SqliteConn() throws Exception {
Class.forName("org.sqlite.JDBC");
System.out.println("spark");
...
}
public static void deleteTables() throws Exception {
Class.forName("ru.yandex.clickhouse.ClickHouseDriver");
System.out.println("OTTl");
...
}
}
I added Thread.sleep in between the threads, it works. It is a bad approach in real world. I may get one more thread which may needs to load diff driver in future. What is the good approach to implement this without fail?

Inheritance and Try-With-Resources

Suppose there are two classes implementing AutoCloseable Interface as below:
public class Closing1 implements AutoCloseable {
private boolean closed;
#Override
public void close() throws Exception {
if (closed) {
throw new Exception("Closed Already");
}
this.closed = true;
System.out.println("Closing1 closed");
}
public boolean isClosed() {
return closed;
}
}
and
public class Closing2 implements AutoCloseable {
private Closing1 cl1;
public Closing2(Closing1 cl1) {
this.cl1 = cl1;
}
#Override
public void close() throws Exception {
if(!cl1.isClosed()) {
throw new Exception("Closing1 not closed");
}
System.out.println("Closing2 closed");
}
}
I find that all variations with try with resources lead to an exception! Is there something I am missing here, or is it just the way TWR is designed?
try(Closing1 c1 = new Closing1();Closing2 c2 = new Closing2(c1)){
System.out.println("Done");
} //Exception while auto closing C2
or
try(Closing1 c1 = new Closing1();Closing2 c2 = new Closing2(c1)){
System.out.println("Done");
c1.close();
} // exception while auto closing c1
Try-with-resources will close the resources in the opposite order of their declaration. This means that c2.close() will be called first, which will throw the exception as you have coded it.
Start with try-with-resources first, https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
As the very first example shows already:
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
people will not necessarily name everything in the chain.
Unless you explicitly need c1 for something (other than closing), in real life your snippet would rather look like
try(Closing2 c2 = new Closing2(new Closing1())){
System.out.println("Done");
}
and you would not call c1.close() in the try-block for sure, as there would be no c1 at all.
Keeping this in mind, throwing an exception from c2 because the contained c1 is not closed, is totally wrong, actually c2 owns the Closing1 object and should invoke close() on it:
class Close1 implements AutoCloseable {
#Override
public void close() throws Exception {
System.out.println("Closing c1");
}
}
class Close2 implements AutoCloseable {
Close1 c1;
Close2(Close1 c1) {
this.c1=c1;
}
#Override
public void close() throws Exception {
System.out.print("Closing c1 from c2: ");
c1.close();
System.out.println("Closing c2");
}
}
void test() {
System.out.println("Before try block");
try(Close2 c2=new Close2(new Close1())) {
System.out.println("In try block");
}
catch(Exception ex) {
System.out.println("Exception: "+ex);
}
finally {
System.out.println("In finally block");
}
System.out.println("After try block");
}
However, if someone gives a name to c1, it will be closed twice, that is where the idempotency comes into the picture, as suggested by someone already:
System.out.println("Before try block");
try(Close1 c1 = new Close1(); Close2 c2 = new Close2(c1)){
System.out.println("In try block");
}
catch(Exception ex){
System.out.println("Exception: "+ex);
}
finally{
System.out.println("In finally block");
}
System.out.println("After try block");
As BufferedReader was mentioned already, this is the close() method it has:
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close();
} finally {
in = null;
cb = null;
}
}
}
If it has in, it gets closed, and nulled (in a finally block, so it happens even if an exception occurs), and all in a thread-safe block. (cb is just an array of characters, it gets null-ed too, simplifying the life of the garbage collector a little). Because of nulling everything in the finally block, any extra calls to this same method will not do anything (apart from synchronizing on the lock for a moment).

Java Try With Resources - Order of Closing Resources

On running the below code
class MyResource1 implements AutoCloseable {
public void close() throws IOException {
System.out.print("1 ");
}
}
class MyResource2 implements Closeable {
public void close() throws IOException {
throw new IOException();
}
}
public class MapAndFlatMap {
public static void main(String[] args) {
try (
MyResource1 r1 = new MyResource1();
MyResource2 r2 = new MyResource2();
) {
System.out.print("T ");
} catch (IOException ioe) {
System.out.print("IOE ");
} finally {
System.out.print("F ");
}
}
}
I am getting the below output
T IOE 1 F
But I was expecting
T 1 IOE F
Even after changing the order of resources in try like the following
MyResource2 r2 = new MyResource2();
MyResource1 r1 = new MyResource1();
There is no change in output .In my understanding the resources will be closed in opposite direction of their declaration . Is it correct ?
It is a documented behavior: "close methods of resources are called in the opposite order of their creation"

Suppressed exception disappeared when using finally?

Here's the code.
public class TestTest {
public static void main (String[] args) throws Exception {
try {
run();
} catch(Exception e) {
printSuppressedExceptions(e);
}
}
public static void printSuppressedExceptions(Throwable t) {
System.out.println(t);
System.out.println("suppressed exceptions: " + t.getSuppressed().length);
}
public static void run() throws Exception {
try(MyResource r = new MyResource("resource");) {
System.out.println("try");
System.getProperty("").length(); // throws illegalArgumentException
} catch(Exception e) {
printSuppressedExceptions(e);
throw e;
} finally {
new MyResource("finally").close();
}
}
}
class MyResource implements AutoCloseable {
private final String name;
public MyResource(String name) {
this.name = name;
}
#Override
public void close() throws Exception {
throw new Exception("exception" + " from " + this.name);
}
}
Since exception thrown from try block suppressed the exception from resource, I got "suppressed exceptions: 1" at first which was understandable. But when an exception was thrown from finally, it seemed like all suppressed exceptions disappeared because I got "java.lang.Exception: exception from finally" followed by "suppressed exceptions: 0" which I think it should be 1.
I browsed the Java tutorials and it definitely says
However, in this example, if the methods readLine and close both throw exceptions, then the method readFirstLineFromFileWithFinallyBlock throws the exception thrown from the finally block; the exception thrown from the try block is suppressed.
From The try-with-resources Statement
How could it happen?
Here is code that does what you would expect:
public class TestTest {
public static void main (String[] args) throws Exception {
try {
run();
} catch(Exception e) {
printSuppressedExceptions(e);
}
}
public static void printSuppressedExceptions(Throwable t) {
System.out.println(t);
System.out.println("suppressed exceptions (" + t.getSuppressed().length + "):");
for (Throwable suppressed : t.getSuppressed()) {
System.out.println(" - " + suppressed);
}
}
public static void run() throws Exception {
Exception exceptionFromCatch = null;
try(MyResource r = new MyResource("resource");) {
System.out.println("try");
System.getProperty("").length(); // throws illegalArgumentException
} catch(Exception e) {
exceptionFromCatch = e;
printSuppressedExceptions(e);
throw e;
} finally {
try {
new MyResource("finally").close();
} catch (Exception e) {
if (exceptionFromCatch!=null) {
e.addSuppressed(exceptionFromCatch);
}
throw e;
}
}
}
}
class MyResource implements AutoCloseable {
private final String name;
public MyResource(String name) {
this.name = name;
}
#Override
public void close() throws Exception {
throw new Exception("exception" + " from " + this.name);
}
}
So lets go trough the try-with-resource part of your code (as introduced in JDK 1.7.0) and see what happens (see What is the Java 7 try-with-resources bytecode equivalent using try-catch-finally? for more details):
the try-with-resource block MyResource r = new MyResource("resource") is executed
the try block is executed and throws an IllegalArgumentException
the try-with-resource block calls close() for all resources (in your example only one)
close() throws an exception, but since the exception from the try block has priority the exception from thrown by close() is suppressed and added via addSuppressed(..)
So that part works like you expected from reading the tutorial.
And now the try-catch-finally part of your code (as in JDK 1.6 and earlier):
the try block is executed and throws an IllegalArgumentException
(the catch block behaves the same way as if there was no catch block)
the finally block is executed and throws an Exception
the exception from the finally block has priority and the one from the try block is suppressed
But this time the word suppressed used in the java tutorial does not stand for "suppressed and added to the actually thrown exception" but "suppressed and lost to nirvana". So it still behaves as in JDK 1.6 and earlier and does not make use of the newly introduced addSuppressed(..) getSuppressed() functionality. That's the reason it doesn't behave like you expected.
I would argue the behaviour you expected wouldn't be logical either. I would like it to behave like this:
...
} finally {
try {
new MyResource("finally").close();
} catch (Exception e) {
if (exceptionFromCatch!=null) {
exceptionFromCatch.addSuppressed(e);
} else {
throw e;
}
}
}
...
That would always give priority to the exception from the try block (as implemented with the new try-with-resource feature) and add the exception from the catch block as suppressed to the list. But that would break compatibility with JDK 1.6, so I guess that's the reason why it doesn't behave like that.

If multiple resources are closed inside a finally block, is exception handling necessary?

A coworker just unsettled me concerning finally blocks. He claimed that if multiple resources are closed inside a finally block, I do not have to worry about exception handling.
So if I close my resources like this
try {
// do stuff
} catch(Exception e) {
// handle stuff
} finally {
resource1.close();
resource2.close();
}
and an exception occurs at resource1.close(), will the close() method of resource2 get called?
A simple check would confirm:
class MyResource implements AutoCloseable {
private final String name;
MyResource(String name) { this.name = name; }
#Override public void close() throws IOException {
System.out.println("Closing " + name);
throw new IOException();
}
}
public static void main(String[] args) throws IOException {
MyResource a = new MyResource("a");
MyResource b = new MyResource("b");
try {
} finally {
a.close();
b.close();
}
}
This would print "Closing a" and then print a stack trace; "Closing b" would not be printed. In contrast:
try (MyResource a = new MyResource("a");
MyResource b = new MyResource("b")) {
}
would print both.
That depends. If the only exception throwing things (explicitly or potentially) you have inside your try-catch block are close operations, you wouldn't need exception handling. However, most of the times, the close operations are themselves declared as throwing exceptions, thus, you'd need to put them inside a try-catch block anyway.

Categories

Resources