Java - catch/rethrow behavior [duplicate] - java

This question already has answers here:
Exception thrown in catch and finally clause
(12 answers)
Closed 1 year ago.
I have this piece of Java code.
void convertFile() {
try{
.....
}catch (Exception e) {
logError("Error in convertJsonFile", e);
throw e;
}finally{
if (writer!=null) {
writer.close();
writer = null;
}
if (fos!=null) {
fos.close();
fos = null;
}
ms2 = System.currentTimeMillis();
logInfo(String.format("Time elapsed: %d seconds.", ((ms2-ms1)/1000)));
logInfo("File conversion complete.");
}
return f + "_changed.xml";
}
The catch block logs and rethrows the Exception.
But it seems the finally block also throws a RuntimeException.
Will the finally block be executed if the catch block rethrows Exception as done here?
If I remember correctly finally block will be executed even in this case.
OK if so... what will happen if we enter the catch block (it rethrows), then we enter the finally block, and the finally block also throws a RuntimeException at this line writer.close(); ? Which exception will be thrown from this whole method - the rethrown one from the catch block, or the RuntimeException from the finally block?!
I think the RuntimeException will be the final outcome of the method and we will never reach the line in the catch block which rethrows. Because I guess the line which rethrows is executed after the finally block. But I am not sure. I got really confused.
Could someone clear my doubts here?
Seems I have forgotten some of these details.
And I have no decent access to the logs, they are in Elastic/Kibana and access to them is a real pain.

Yes, finally block will be executed
The exception from finally block will be thrown in this case. Thus, exception from catch block will be lost.

Related

try-with-resource vs ordinary code with explicit close()-call [duplicate]

This question already has answers here:
What's the purpose of try-with-resources statements?
(7 answers)
Closed 2 years ago.
I have been looking at code and I have seen try with resources. I have used the standard try-catch statement before and it looks like they do the same thing. So my question is Try With Resources vs Try-Catch what are the differences between those, and which is better.
Here is a try with resources :
objects jar = new objects("brand");
objects can= new objects("brand");
try (FileOutputStream outStream = new FileOutputStream("people.bin")){
ObjectOutputStream stream = new ObjectOutputStream(outStream);
stream.writeObject(jar);
stream.writeObject(can);
stream.close();
} catch(FileNotFoundException e) {
System.out.println("sorry it didn't work out");
} catch(IOException f) {
System.out.println("sorry it didn't work out");
}
The main point of try-with-resources is to make sure resources are closed reliably without possibly losing information.
When you don't use try-with-resources there's a potential pitfall called exception-masking. When code in a try block throws an exception, and the close method in the finally also throws an exception, the exception thrown by the try block gets lost and the exception thrown in the finally gets propagated. This is usually unfortunate, since the exception thrown on close is something unhelpful while the informative one is the one thrown from within the try block. (So instead of seeing the SQLException that tells you which referential integrity constraint was violated, you're shown something like BrokenPipeException where closing the resource failed.)
This exception-masking is an annoying problem that try-with-resources prevents from happening.
As part of making sure exception-masking wouldn't lose important exception information, when try-with-resources was developed they had to decide what to do with the exceptions thrown from the close method.
With try-with-resources, if the try block throws an exception and the close method also throws an exception, then the exception from the close block gets tacked on to the original exception:
... there are situations where two independent exceptions can be thrown in sibling code blocks, in particular in the try block of a try-with-resources statement and the compiler-generated finally block which closes the resource. In these situations, only one of the thrown exceptions can be propagated. In the try-with-resources statement, when there are two such exceptions, the exception originating from the try block is propagated and the exception from the finally block is added to the list of exceptions suppressed by the exception from the try block. As an exception unwinds the stack, it can accumulate multiple suppressed exceptions.
On the other hand if your code completes normally but the resource you're using throws an exception on close, that exception (which would get suppressed if the code in the try block threw anything) gets thrown. That means that if you have some JDBC code where a ResultSet or PreparedStatement is closed by try-with-resources, an exception resulting from some infrastructure glitch when a JDBC object gets closed can be thrown and can rollback an operation that otherwise would have completed successfully.
Without try-with-resources whether the close method exception gets thrown is up to the application code. If it gets thrown in a finally block when the try block throws an exception, the exception from the finally block will mask the other exception. But the developer has the option of catching the exception thrown on close and not propagating it.
You missed something, the finally block. The try-with-resouces will make it something like,
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream("people.bin");
ObjectOutputStream stream = new ObjectOutputStream(outStream);
stream.writeObject(jar);
stream.writeObject(can);
stream.close();
} catch(FileNotFoundException e) {
System.out.println("sorry it didn't work out");
} catch(IOException f) {
System.out.println("sorry it didn't work out");
} finally {
if (outStream != null) {
try {
outStream.close();
} catch (Exception e) {
}
}
}
Which means you really wanted something like (never swallow exceptions),
try (FileOutputStream outStream = new FileOutputStream("people.bin");
ObjectOutputStream stream = new ObjectOutputStream(outStream);) {
stream.writeObject(jar);
stream.writeObject(can);
// stream.close(); // <-- closed by try-with-resources.
} catch(FileNotFoundException e) {
System.out.println("sorry it didn't work out");
e.printStackTrace();
} catch(IOException f) {
System.out.println("sorry it didn't work out");
e.printStackTrace();
}
The only difference is that try-resource is adding automatically resource.close();
as you would do in finally block
Any object (either the class or their superclass) that implements java.lang.AutoCloseable or java.io.Closeable
can only be used in try-with-resource clause.
AutoClosable interface is the parent interface and Closable interface extends the AutoClosable interface.AutoClosable interface has method close which throws Exception while Closable interface has method that throws IOException.
We can also have catch and finally block followed by try-with-resource like ordinary try, catch and finally, but catch and finally block only get executed once the resource declared inside the try-with-resource clause is closed.
Succinctly it is syntactic sugar to support the AutoClosable interface and call the close() method for you for any outcome.

what's try method means in java? [duplicate]

This question already has answers here:
What's the purpose of try-with-resources statements?
(7 answers)
Closed 2 years ago.
I have been looking at code and I have seen try with resources. I have used the standard try-catch statement before and it looks like they do the same thing. So my question is Try With Resources vs Try-Catch what are the differences between those, and which is better.
Here is a try with resources :
objects jar = new objects("brand");
objects can= new objects("brand");
try (FileOutputStream outStream = new FileOutputStream("people.bin")){
ObjectOutputStream stream = new ObjectOutputStream(outStream);
stream.writeObject(jar);
stream.writeObject(can);
stream.close();
} catch(FileNotFoundException e) {
System.out.println("sorry it didn't work out");
} catch(IOException f) {
System.out.println("sorry it didn't work out");
}
The main point of try-with-resources is to make sure resources are closed reliably without possibly losing information.
When you don't use try-with-resources there's a potential pitfall called exception-masking. When code in a try block throws an exception, and the close method in the finally also throws an exception, the exception thrown by the try block gets lost and the exception thrown in the finally gets propagated. This is usually unfortunate, since the exception thrown on close is something unhelpful while the informative one is the one thrown from within the try block. (So instead of seeing the SQLException that tells you which referential integrity constraint was violated, you're shown something like BrokenPipeException where closing the resource failed.)
This exception-masking is an annoying problem that try-with-resources prevents from happening.
As part of making sure exception-masking wouldn't lose important exception information, when try-with-resources was developed they had to decide what to do with the exceptions thrown from the close method.
With try-with-resources, if the try block throws an exception and the close method also throws an exception, then the exception from the close block gets tacked on to the original exception:
... there are situations where two independent exceptions can be thrown in sibling code blocks, in particular in the try block of a try-with-resources statement and the compiler-generated finally block which closes the resource. In these situations, only one of the thrown exceptions can be propagated. In the try-with-resources statement, when there are two such exceptions, the exception originating from the try block is propagated and the exception from the finally block is added to the list of exceptions suppressed by the exception from the try block. As an exception unwinds the stack, it can accumulate multiple suppressed exceptions.
On the other hand if your code completes normally but the resource you're using throws an exception on close, that exception (which would get suppressed if the code in the try block threw anything) gets thrown. That means that if you have some JDBC code where a ResultSet or PreparedStatement is closed by try-with-resources, an exception resulting from some infrastructure glitch when a JDBC object gets closed can be thrown and can rollback an operation that otherwise would have completed successfully.
Without try-with-resources whether the close method exception gets thrown is up to the application code. If it gets thrown in a finally block when the try block throws an exception, the exception from the finally block will mask the other exception. But the developer has the option of catching the exception thrown on close and not propagating it.
You missed something, the finally block. The try-with-resouces will make it something like,
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream("people.bin");
ObjectOutputStream stream = new ObjectOutputStream(outStream);
stream.writeObject(jar);
stream.writeObject(can);
stream.close();
} catch(FileNotFoundException e) {
System.out.println("sorry it didn't work out");
} catch(IOException f) {
System.out.println("sorry it didn't work out");
} finally {
if (outStream != null) {
try {
outStream.close();
} catch (Exception e) {
}
}
}
Which means you really wanted something like (never swallow exceptions),
try (FileOutputStream outStream = new FileOutputStream("people.bin");
ObjectOutputStream stream = new ObjectOutputStream(outStream);) {
stream.writeObject(jar);
stream.writeObject(can);
// stream.close(); // <-- closed by try-with-resources.
} catch(FileNotFoundException e) {
System.out.println("sorry it didn't work out");
e.printStackTrace();
} catch(IOException f) {
System.out.println("sorry it didn't work out");
e.printStackTrace();
}
The only difference is that try-resource is adding automatically resource.close();
as you would do in finally block
Any object (either the class or their superclass) that implements java.lang.AutoCloseable or java.io.Closeable
can only be used in try-with-resource clause.
AutoClosable interface is the parent interface and Closable interface extends the AutoClosable interface.AutoClosable interface has method close which throws Exception while Closable interface has method that throws IOException.
We can also have catch and finally block followed by try-with-resource like ordinary try, catch and finally, but catch and finally block only get executed once the resource declared inside the try-with-resource clause is closed.
Succinctly it is syntactic sugar to support the AutoClosable interface and call the close() method for you for any outcome.

Does finally completely execute if an exception is thrown within finally block

so I have a bit of code here and I'm not sure entirely how it would react in the event that the reader.close() method throws an exception.
public void someMethod(String s) throws IOException{
BufferedReader reader = Files.newBufferedReader(filePath,cs);
listRWLock.readLock().lock();
try{
//miscellaneous code involving reading
}finally{
reader.close()
listRWLock.readLock().unlock()
}
}
ListRWLock is a ReentrantReadWriteLock. In the event that the reader.close() method throws an exception, would the statement after it fail to execute? I've tried searching for the topic, and while I've gotten something about finally executing in the event of return statements, I haven't managed to find details on what happens if an exception is thrown within the finally block.
Thanks in advance.
Basically, finally clauses are there to ensure proper release of a resource. However, if an exception is thrown inside the finally block, that guarantee goes away.
An issue for which there's no really neat solution is that code in the finally block could itself throw an exception. In this case, the exception in the finally block would be thrown from the exception instead of any exception occurring inside the try block. Since code in the finally block is intended to be "cleanup" code, we could decide to treat exceptions occurring there as secondary, and to put an excplicit catch:
public int readNumber(File f) throws IOException, NumberFormatException {
BufferedReader br = new BufferedReader(new
InputStreamReader(new FileInputStream(f), "ASCII"));
try {
return Integer.parseInt(br.readLine());
} finally {
try { br.close(); } catch (IOException e) {
// possibly log e
}
}
}
Some other things to note about finally blocks:
The same 'overriding' problem that we mentioned with exceptions
occurs when returning a value from a finally block: this would
override any return value that the code in the try block wanted to
return. In practice, returning a value from a finally clause is rare
and not recommended.
Actually exiting the program (either by calling System.exit() or by
causing a fatal error that causes the process to abort: sometimes
referred to informally as a "hotspot" or "Dr Watson" in Windows)
will prevent your finally block from being executed!
There's nothing to stop us nesting try/catch/finally blocks (for
example, putting a try/finally block inside a try/catch block, or
vice versa), and it's not such an uncommon thing to do.
You can do something like this:
try{
//miscellaneous code involving reading
}finally{
handlePossibleException(reader);
listRWLock.readLock().unlock()
}
handlePossibleException(BufferedReader reader) {
try {
if (reader != null) {
reader.close();
}
} catch( Exception e ) {
log.e( "reader.close() Exception: ", e );
}
}
You should test this,
but if try throws IO Exception, then your reader wont close.
Maybe have
catch(IOException ex){
reader.close()
An exception can happen anywhere in your code, including finally block, so you have to catch it as anywhere else in your code. Check the following post to get some ideas about the ways you can handle such situation:
throws Exception in finally blocks

Java exception not caught?

I have a small theoretical problem with try-catch constructions.
I took a practical exam yesterday about Java and I don't understand following example:
try {
try {
System.out.print("A");
throw new Exception("1");
} catch (Exception e) {
System.out.print("B");
throw new Exception("2");
} finally {
System.out.print("C");
throw new Exception("3");
}
} catch (Exception e) {
System.out.print(e.getMessage());
}
The question was "what the output will look like?"
I was pretty sure it would be AB2C3, BUT suprise suprise, it's not true.
The right answer is ABC3 (tested and really it's like that).
My question is, where did the Exception("2") go?
From the Java Language Specification 14.20.2.:
If the catch block completes abruptly for reason R, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly for reason R.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
So, when there is a catch block that throws an exception:
try {
// ...
} catch (Exception e) {
throw new Exception("2");
}
but there is also a finally block that also throws an exception:
} finally {
throw new Exception("3");
}
Exception("2") will be discarded and only Exception("3") will be propagated.
Exceptions thrown in finally block suppress the exception thrown earlier in try or catch block.
Java 7 example: http://ideone.com/0YdeZo
From Javadoc's example:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
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.
The new try-with syntax of Java 7 adds another step of exception suppression: Exceptions thrown in try block suppress those thrown earlier in try-with part.
from same example:
try (
java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {
String newLine = System.getProperty("line.separator");
String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
An exception can be thrown from the block of code associated with the
try-with-resources statement. In the above example, an exception can
be thrown from the try block, and up to two exceptions can be thrown
from the try-with-resources statement when it tries to close the
ZipFile and BufferedWriter objects. If an exception is thrown from the
try block and one or more exceptions are thrown from the
try-with-resources statement, then those exceptions thrown from the
try-with-resources statement are suppressed, and the exception thrown
by the block is the one that is thrown by the
writeToFileZipFileContents method. You can retrieve these suppressed
exceptions by calling the Throwable.getSuppressed method from the
exception thrown by the try block.
In code from question, each block is plainly discarding the old exception, not even logging it, not good when you are trying to resolve some bugs:
http://en.wikipedia.org/wiki/Error_hiding
Since throw new Exception("2"); is thrown from catch block and not try, it won't be caught again.
See 14.20.2. Execution of try-finally and try-catch-finally.
This is what happening:
try {
try {
System.out.print("A"); //Prints A
throw new Exception("1");
} catch (Exception e) {
System.out.print("B"); //Caught from inner try, prints B
throw new Exception("2");
} finally {
System.out.print("C"); //Prints C (finally is always executed)
throw new Exception("3");
}
} catch (Exception e) {
System.out.print(e.getMessage()); //Prints 3 since see (very detailed) link
}
Your Question is very obvious, and the answer is simple to the same extent..
The Exception object with message as "2" is overwritten by the Exception object with message as "3" .
Explanation :
When an Exception occur, its object it thrown to catch block to handle. But when exception occur in catch block itself, its object is transferred to OUTER CATCH Block(if any) for exception Handling. And Same happened Here. The Exception Object with message "2" is transferred to OUTER catch Block . But wait.. Before leaving inner try-catch block it HAS TO EXECUTE FINALLY. Here occurred the change we are concerned about. A new EXCEPTION object(with message "3") is thrown out or this finally block which replaced the already thrown Exception object(with message "2").As a result of which, when the message of Exception object is printed , we got overridden value i.e. "3" and not "2".
Keep Remember :Only one exception object can be handled by on CATCH block.
The finally block always runs. Either you return from inside the try block or an exception is thrown. The exception thrown in the finally block will override the one thrown in the catch branch.
Additionally, throwing an exception will not cause any output by itself. The line throw new Exception("2"); will not write anything out.
According to your code:
try {
try {
System.out.print("A");
throw new Exception("1"); // 1
} catch (Exception e) {
System.out.print("B"); // 2
throw new Exception("2");
} finally { // 3
System.out.print("C"); // 4
throw new Exception("3");
}
} catch (Exception e) { // 5
System.out.print(e.getMessage());
}
As you can see here:
print A and throws exception # 1;
this exception has caught by catch statement and print B - # 2;
block finally # 3 executes after try-catch (or only try, if hadn't occurred any exception) statement and prints C - # 4 and thrown new exception;
this one has caught by external catch statement # 5;
Result is ABC3. And 2 is omitted at the same way as 1

Java catching exceptions and subclases

Hello,
In Java if a method like BufferedReader.read() says it can throw an IOException and I try to catch a FileNotFoundException and an IOException in two catch blocks, what catch blocks will be entered if the file doesn't exist?
Does it enter only the most specific or both?
The first coded catch that matches the exception will be entered.
Edited to incorporate comment from Azodius
For example:
try {
bufferedReader.read();
} catch (FileNotFoundException e) {
// FileNotFoundException handled here
} catch (IOException e) {
// Other IOExceptions handled here
}
This following code does not compile:
try {
bufferedReader.read();
} catch (IOException e) {
// All IOExceptions (and of course subclasses of IOException) handled here
} catch (FileNotFoundException e) {
// Would never enter this block, because FileNotFoundException is a IOException
}
Compiler message says:
Unreachable catch block for FileNotFoundException. It is already handled by the catch block for IOException
Only the first catch block encountered where the exception type of the catch block matches the type of the exception being thrown will be run (more specifically, the first catch block where (e instaceof <exception type>)==true will be run). None of the other catch blocks will be run.
For example
try{
BufferedReader.read();
}
catch(FileNotFoundException e){System.out.println("FileNotFoundException");}
catch(IOException e){System.out.println("IOException");}
Will print FileNotFoundException if BufferedReader.read() throws a FileNotFoundException.
Note that the following doesn't actually compile:
try{
BufferedReader.read();
}
catch(IOException e){System.out.println("IOException");}
catch(FileNotFoundException e){System.out.println("FileNotFoundException");}
because Java realizes that it is not possible for the FileNotFoundException to be caught because all FileNotFoundExceptions are also IOExceptions.
The first one which is suitable for that type of exception (and only that). So if you catch the two exception types above in the order you list them, a FileNotFoundException will be caught.
Specific exception is caught first. and it's a compile time error if generic exception is caught befor specific one.

Categories

Resources