I'm reading Java from HeadFirst. I started reading the chapter about Exception Handling. There was code in the book that I executed on my computer.
import javax.sound.midi.*;
class PlayMusic
{
public void play()
{
try{
Sequencer sq = MidiSystem.getSequencer();
System.out.println("We got a sequencer");
}
catch(MidiUnavailableException ex)
{
System.out.println("Bummer!");
ex.printStackTrace();
}
}
public static void main(String[] args)
{
PlayMusic pm = new PlayMusic();
pm.play();
}
}
When I remove the try-catch block, the compiler raises a MidiUnavailableException error. I used try-catch to catch that exception, but System.out.println("Bummer"); doesn't get executed. Instead, the try block is executed.
What is happening here?
When you get a compiler error, it means the method may throw an MidiUnavailableException. At runtime is when exceptions are thrown, and if the action succeeds then the catch block will not be entered. If you have a finally block, that is guaranteed to be entered.
MidiUnavailableException is a checked exception, so you are required to include the catch block in order for the code to compile. However, there is no guarantee that the exception will actually be thrown when your program executes. In your case, it isn't being thrown, so the code in your try block executes normally and your printout for the error never gets called.
Related
I am considering this from the Java Language Specification:
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).
I have a block as follows:
try {
.. do stuff that might throw RuntimeException ...
} finally {
try {
.. finally block stuff that might throw RuntimeException ...
} catch {
// what to do here???
}
}
Ideally, I would want any RuntimeException thrown in the finally block to escape, only if it would not cause a RuntimeException thrown in the main try block to be discarded.
Is there any way in Java for me to know whether the block that is associated with a finally block completed normally or not?
I'm guessing I could just set a boolean as the very last statement of the main try block (e.g., completedNormally = true. Is that the best way, or is there something better / more standard?
I believe the key is to not lose the original cause if any.
If we look at how try-with-resources behave:
private static class SomeAutoCloseableThing implements AutoCloseable {
#Override
public void close() {
throw new IllegalStateException("closing failed");
}
}
public static void main(String[] args) {
try (SomeAutoCloseableThing thing = new SomeAutoCloseableThing()) {
throw new IllegalStateException("running failed");
}
}
We end up with:
Exception in thread "main" java.lang.IllegalStateException: running failed
at Main.main(Main.java:16)
Suppressed: java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:9)
at Main.main(Main.java:17)
This stack trace is great as we see both exceptions, i.e. we don't lose the running failed one.
Implementing this without try-with-resources, the wrong way:
public static void main(String[] args) {
SomeAutoCloseableThing thing = new SomeAutoCloseableThing();
try {
throw new IllegalStateException("running failed");
} finally {
thing.close();
}
}
We end up with:
Exception in thread "main" java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:9)
at Main.main(Main.java:19)
We don't know that running failed occurred too as we broke the control flow, that's quite bad if you need to debug such a case.
Implementing this without try-with-resources, the right way (in my opinion), is to "log and forget" the exception that occurred in the finally block:
public static void main(String[] args) {
SomeAutoCloseableThing thing = new SomeAutoCloseableThing();
try {
throw new IllegalStateException("running failed");
} finally {
try {
thing.close();
} catch (Exception e) {
LoggerFactory.getLogger(Main.class).error("An error occurred while closing SomeAutoCloseableThing", e);
}
}
}
We end up with:
17:10:20.030 [main] ERROR Main - An error occurred while closing SomeAutoCloseableThing
java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:10) ~[classes/:?]
at Main.main(Main.java:21) [classes/:?]
Exception in thread "main" java.lang.IllegalStateException: running failed
at Main.main(Main.java:18)
Not as good as the try-with-resources approach, but at least we know what actually happened, nothing got lost.
I assume your finally block is doing cleanup. A good way to accomplish such cleanup is to create a class that implements AutoCloseable, so your code can place it in a try-with-resources statement:
class DoStuff
implements AutoCloseable {
public void doStuffThatMightThrowException() {
// ...
}
#Override
public void close() {
// do cleanup
}
}
(Notice that it does not need to be a public class. In fact, it probably shouldn’t be.)
The code in your example would then look like this:
try (DoStuff d = new DoStuff()) {
d.doStuffThatMightThrowException();
}
As for what happens if an exception is thrown during the cleanup: it becomes a suppressed exception. It won’t show up in a stack trace, but you can access it if you really want to (which you probably won’t).
I don't think there is an idiomatic solution to this problem, partly because you normally use finally to clean-up resources disregarding completely if the code that allocated the resource terminated normally or not.
For example you finally close a connection, but the transaction will be rolled back in the catch block or committed as a last statement of the code block wrapped in the try.
Concerning an throwable thrown inside the finally block, you should decide which exception is most important to pass on to the caller. You can ultimately create your own exception which holds reference to both exceptions, in that case you need to declare a variable initialized outside the try and set inside the catch.
For example, in the following code you either complete normally or throw an exception, while having tried a recovery (rolling back a transaction) and tried a clean-up in finally.
Either can fail and you wrap what you think is the most important data in the exception you finally throw.
private void foo() throws SQLException {
Throwable firstCause = null;
try {
conn.prepareStatement("...");
// ...
conn.commit();
} catch (SQLException e) {
firstCause = e;
conn.rollback();
throw e;
} finally {
try {
conn.close();
} catch (Exception e) {
throw new RuntimeException(firstCause);
// or
// throw new RuntimeException(e);
// or
// throw new MyException(e,firstCause);
}
}
}
You could capture the original exception and re-throw it from within finally block.
Code below does just that and the exception thrown out of the method below will have the stacktrace and the cause dictated by the outer RuntimeException.
private void testException() {
RuntimeException originalFailure = null;
try {
throw new RuntimeException("Main exception");
} catch (RuntimeException e) {
originalFailure = e;
} finally {
try {
throw new RuntimeException("Final exception");
} catch (RuntimeException e) {
if (originalFailure != null) {
throw originalFailure;
} else {
throw e; //OR do nothing
}
}
}
}
This question already has answers here:
Multiple returns: Which one sets the final return value?
(7 answers)
Closed 4 years ago.
I am reviewing for OCP and I stumbled upon this scenario with Exceptions.
Typically, we encounter Suppressed Exceptions in try-with-resource. if the try block and close() method both throws an Exception, only the one in try block will be handled. The exception thrown in close() will be suppressed.
I am experimenting other ways to encounter suppressed exceptions. Running methodTwo() will just throw NullPointerException. It will be catched but it is not suppressed. What happened to IllegalArgumentException?
public class Main {
public static void main(String[] args) {
try {
methodTwo();
} catch (Exception e) {
e.printStackTrace();
for(Throwable t : e.getSuppressed()) {
System.out.println(t.getMessage());
}
}
}
static void methodTwo() {
try {
throw new IllegalArgumentException("Illegal Argument");
} finally {
throw new NullPointerException("Null Pointer");
}
}
}
as mentioned by comments, finally always executed if any exception or return happen. it is because of assurance of free resource like files and etc. if you don't return or throw new exception in finally, it return exception or value that set before.
you can change value that return in finally block too for example:
class A
{
public int value; // it is not good but only for test
}
public class Tester
{
public static void main(String[] args) {
System.out.println(method1().value); // print 10
}
private static A method1() {
A a = new A();
try
{
a.value = 5;
return a;
} finally
{
a.value = 10;
}
}
}
you can throw exception instead of throwing new value too and return value or last exception discarded. (but all of this is not good in programming design)
when you working with files, because there is nothing like destructor in java like c++ (although there is finally but it is different) you must using try finally (or for new way, use try-with-resource) to free resource obtained from system.
As explained here by #polygenelubricants
A try statement with a finally block is executed by first executing the try block. Then there is a choice:
If execution of the try block completes normally, [...]
If execution of the try block completes abruptly because of a throw of a value V, [...]
If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice:
If the finally block completes normally, [...]
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
For more detail , go to oracle documentation
I have java project contains around 10-15 java files and number of classes. I want to return exit code 1 from catch block inside the main() if any exception occurred any where through out these programs. However all of the classes has exception catch blocks so that exceptions will be handled there itself and catch block inside main() cannot "see" it.
Is there any way to check whether any exception occurred anywhere in the project inside main() of start point without change any code in other files but only at start point.
Thanks
Noushad
You can't. You need to modify the other classes to throw an exception to the caller so that you can catch the exception in main and return the exit code you want.
Write a common "logging" function and call it from any relevant catch block. If you need to exit the program, use System.exit.
public class Defines {
public static LogException(Exception exception) {
...
if (ShouldExitFromException(exception))
System.exit(1);
}
}
elsewhere in your code:
try {
// some code
} catch (Exception exception) {
Defines.LogException(exception);
}
But it will depend what your other catch blocks are actually doing, and to be honest, this all sounds like a bad idea. Logging exceptions might be ok, so you know where and when they're happening, but exiting the program for even ones that have been handled properly is not a good idea.
Throw exception from all methods of all classes and catch it in Main method's catch block. Log exception and then do exit.
public static void main(String[] args)
{
try
{
ClassA.methodX();
ClassB.method();
}
catch(Exception e) //use specific exception class
{
e.printsttrace();
System.exit(1);
}
}
Class A
class classA
{
public static void methodX() throws Exception
{
try{
//perform some operation
}catch(Exception e)
{
//throw exception from here.
}
}
What should we do in catch block when we can't do anything useful for program work recovery? Say it's simple program, so Logging does not suitable too. For example:
public class Test {
public static void main(String[] args) {
try {
Scanner in = new Scanner(Paths.get("SomeFile.txt"));
//...
} catch (IOException exc){
//System.out.println("Error"); — erroneous, right?
}
}
}
If it's a simple program, either do nothing (don't catch the exception, add throws clause to your main method), or print some error message in the catch block (preferably to System.err). The latter option only makes sense if there is no more code after the catch block (since you don't want to execute any code after the exception is caught).
I have a Java Program where I get data from a different source. some times while reading I see Exception and the program is exiting.
Mine is in a program that runs every 10minutes.
Public static void main(Strings[] args)
{
...readsource();
}
Private static void readsource() throws IOException
{
...
}
Issue:
I am able to get/See the Exception. But I want the program to continue
To that what is the best logic? I dont see try-catch-finally also is not addressing ..I want the program to continue even after seing the exception (I mean the next iteration should continue). This looks to be a Basic issue not sure how to address this...
Then you need to catch the exception, which you are currently not doing.
try {
readsource();
} catch (IOException e) {
// do something, never catch an exception and not do anything
}
//continue.
Note that exceptions usually indicate something is wrong. Unless you are going to do something about the exception, it might be better to fix the condition causing the exception....
You have to provide an error handler in your method, i.e. surround the call to readsource() with a try-catch block.
public static void main(Strings[] args)
{
try{
...readsource();
}
catch(IOException ioe){
//handle the error here,e.g don't do anything or simply log it
}
}
If you don't rethrow the exception in the catch block, execution will fall off the end of the catch block and continue as if there was no exception.
If you mean you'd like to recall the method wether an Exception was thrown or not just place this in a while loop i.e:
Public static void main(Strings[] args)
{
boolean run=true;
while(run) {
try {
System.out.print("Hello,");
readsource();
throw new IOException();
if(1==2)run=false;//stop the loop for whatever condition
} catch(IOException ioe) {
ioe.printStackTrace();
}
System.out.println(" world!");
}
}
}
Private static void readsource() throws IOException
{
...
}