Why is the code
void methodThrowsException() /*throws Exception*/{
try {
// throw new Exception();
} catch (Exception e) {
throw e;
}
}
well compiled?
AFAIK compiler doesn't analyse code for can it throw an exception or not.
Here obvious throw e; will never run (due to commented // throw new Exception();), but why does compiler know this?
The javac compiler really doesn't do much of optimisation. But simple dead code detections and optimisations are yet possible.
In your example: the compiler can easily detect that the try block is empty. Empty try blocks can't throw, so all catch block code is essentially dead.
So the compiler could go in and simple drop the whole try/catch altogether here. Then there is nothing left that could throw an exception.
Which, when we use javap is exactly what we find in bytecode:
void methodThrowsException();
Code:
0: return
And yes, the other answer is fully correct: this only works this way because you are using Exception, a more specific (checked) subclass will lead to a compiler error.
The compiler will detect specific checked exception that are not thrown e.g.
void methodThrowsException() {
try {
} catch (URISyntaxException e) {
throw e;
}
}
will result in compiler error:
exception java.net.URISyntaxException is never thrown in body of corresponding try statement
but it won't check runtime exceptions, or the exception hierarchy root types like Exception, Error, Throwable. This is explained in JLS 11.2.3. Exception Checking.
Related
I have the following Java code (that I thought was OK) but the IDE is warning me that "IOExcpetion e is immediately rethrown."
I'm new to exception handling in Java, and I wasn't aware there was anything wrong with doing that.
From what I'm reading, it looks like my other options is to simply delete the catch block and replace it with a finally block... but then it warns that the finally block is empty.
I don't have any ideas on what I should do differently.
private InputStream getFlutterAssetAsInputStream(String fromAsset) throws IOException {
String assetPath = binding
.getFlutterAssets()
.getAssetFilePathBySubpath(fromAsset, PACKAGE_NAME);
try {
return binding.getApplicationContext().getAssets().open(assetPath);
} catch (IOException e) {
throw e;
}
}
This
try {
return binding.getApplicationContext().getAssets().open(assetPath);
}
catch (IOException e) {
throw e;
}
is functionally equivalent to this:
return binding.getApplicationContext().getAssets().open(assetPath);
Your IDE is telling you that your try-catch is pointless. It does nothing.
So what do you want to do?
Pass the exception on to your caller? In which case get rid of the try-catch
Signal a different exception on to the caller - maybe one with a more appropriate error message for the specific circumstances? Then make and throw a new exception object with a better error message.
Do something to handle the situation - at the very least, maybe display an error message? Log the event to enable debugging? Then write code in the catch-block to do that. And then you have to decide what happens next.
Fundamentally, this is a design issue. IO errors happen. So how does this method that you're writing want to handle IO errors?
When the run time error occurs it exits the try block. It will throw only one exception and enter the catch block. Then why do I need multiple catch blocks? Where are multi-catch blocks used?
Also, I can also use Throwable to catch any exception. Is that right?
The 'compiler' isn't doing any of this; the compiler is not around. Exceptions are a runtime phenomenon.
Your question appears to be asking how the runtime exception dispatcher picks an exception handler: it is based on type matching.
When you say 'enter the catch block', that is not correct. It selects the first catch-block whose argument type is assignment-compatible with the exception actually thrown.
If you always write catch (Exception ex) then this will catch any exception, since Exception is a superclass of all exception types, and if this is the first such catch block no other will be considered. But this is not always an appropriate exception-handling style; you may be advised to be more specific.
Perhaps this is a good way to understand multiple catch-blocks: you're saying "if it's an X-type exception then do this; otherwise if it's a Y-type exception then do this other thing; otherwise if it's a Z-type exception then a third thing".
FWIW, you rarely want to write catch (Throwable th) unless you're fully aware of the mechanisms you're interfering with by so doing.
Well, you can use a multi catch block to in order to catch different types of exceptions. Let's say you have a custom exception MyCoolExn that implements Throwable.
try {
// run piece of code
} catch (MyCoolExn e) { // catching your custom exception
System.out.println("custom exception occurred");
} catch (Throwable e) { // catch any other exception
System.out.println("an unknown exception occurred ");
}
Note that the order of the blocks is important. If you swap them, MyCoolExn will never be caught, as the Trowable block will catch everything
In Java, is there an elegant way to detect if an exception occurred prior to running the finally block? When dealing with "close()" statements, it's common to need exception handling within the finally block. Ideally, we'd want to maintain both exceptions and propagate them up (as both of them may contain useful information). The only way I can think of to do this is to have a variable outside the try-catch-finally scope to save a reference to a thrown exception. Then propagate the "saved" exception up with any that occur in the finally block.
Is there a more elegant way of doing this? Perhaps an API call that will reveal this?
Here's some rough code of what I'm talking about:
Throwable t = null;
try {
stream.write(buffer);
} catch(IOException e) {
t = e; //Need to save this exception for finally
throw e;
} finally {
try {
stream.close(); //may throw exception
} catch(IOException e) {
//Is there something better than saving the exception from the exception block?
if(t!=null) {
//propagate the read exception as the "cause"--not great, but you see what I mean.
throw new IOException("Could not close in finally block: " + e.getMessage(),t);
} else {
throw e; //just pass it up
}
}//end close
}
Obviously, there are a number of other similar kludges that might involve saving the exception as an member variable, returning it from a method, etc... but I'm looking for something a bit more elegant.
Maybe something like Thread.getPendingException() or something similar? For that matter, is there an elegant solution in other languages?
This question actually spawned from comments in another question that raised an interesting question.
Your idea about setting a variable outside the scope of the try/catch/finally is correct.
There cannot be more than one exception propagating at once.
Instead of using a Boolean flag, I would store a reference to the Exception object.
That way, you not only have a way to check whether an exception occurred (the object will be null if no exception occurred), but you'll also have access to the exception object itself in your finally block if an exception did occur. You just have to remember to set the error object in all your catch blocks (iff rethrowing the error).
I think this is a missing C# language feature that should be added. The finally block should support a reference to the base Exception class similar to how the catch block supports it, so that a reference to the propagating exception is available to the finally block. This would be an easy task for the compiler, saving us the work of manually creating a local Exception variable and remembering to manually set its value before re-throwing an error, as well as preventing us from making the mistake of setting the Exception variable when not re-throwing an error (remember, it's only the uncaught exceptions we want to make visible to the finally block).
finally (Exception main_exception)
{
try
{
//cleanup that may throw an error (absolutely unpredictably)
}
catch (Exception err)
{
//Instead of throwing another error,
//just add data to main exception mentioning that an error occurred in the finally block!
main_exception.Data.Add( "finally_error", err );
//main exception propagates from finally block normally, with additional data
}
}
As demonstrated above... the reason that I'd like the exception available in the finally block, is that if my finally block did catch an exception of its own, then instead of overwriting the main exception by throwing a new error (bad) or just ignoring the error (also bad), it could add the error as additional data to the original error.
You could always set a boolean flag in your catch(es). I don't know of any "slick" way to do it, but then I'm more of a .Net guy.
Use logging...
try {
stream.write(buffer);
} catch(IOException ex) {
if (LOG.isErrorEnabled()) { // You can use log level whatever you want
LOG.error("Something wrong: " + ex.getMessage(), ex);
}
throw ex;
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ex) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not close in finally block", ex);
}
}
}
}
In vb.net, it's possible to use a "Catch...When" statement to grab an exception to a local variable without having to actually catch it. This has a number of advantages. Among them:
If nothing is going to 'ultimately' catch the exception, an unhandled exception trap will be fired from the spot of the original exception. Much nicer than having the debugger trap at the last rethrow, especially since information that might be needed for debugging won't yet have gone out of scope or been swept up by 'finally' statements.
Although a rethrow won't clear the stack trace the way "Throw Ex" would, it will still often jinx the stack trace. If the exception isn't caught, the stack trace will be clean.
Because this feature is unsupported in vb, it may be helpful to write a vb wrapper to implement the code in C (e.g. given a MethodInvoker and an Action(Of Exception), perform the MethodInvoker within a "Try" and the Action in a "Finally".
One interesting quirk: it's possible for the Catch-When to see an exception which will end up getting overwritten by a Finally-clause exception. In some cases, this may be a good thing; in other cases it may be confusing. In any event, it's something to be aware of.
I am a Java beginner and knows that try...catch statements are used to handle exceptions; means when an exception is thrown by try block, catch block is executed. So,my question is when I tried the following code (without try catch) it throws a unreported IOException in read() method but when I use try catch it works fine.
Why doesn't the control get transferred to catch statement when the above mentioned exception occurs in the try block and exception occured is printed?
here is my code:
class Test00 {
public static void main(String args[]) {
char ch;
try {
ch=(char)System.in.read();//here exception is thrown without using try..catch
System.out.println(ch);
} catch(Exception e) {
System.out.print("exception occured");
}
}
}
I think the compiler is saying to throw an exception,that's why the code worked with try catch.But why not the catch block is executed?is i am getting something wrong.
The compiler is telling you that the exception could be thrown, and that you have to cater for that possibility.
The compiler is doing a static analysis of your code. It can't tell how the code will actually run in practise.
This can be frustrating. e.g. if I write:
new URL("http://www.stackoverflow.com");
the compiler will insist that I catch a MalformedURLException. It's clear that URL is fine, but the compiler warns me since I could construct a URL object using:
new URL(potentiallyDubiousUserInput);
and I can't guarantee what that string potentiallyDubiousUserInput is going to be.
These are known as checked exceptions and you have to handle them (either catch or declare them to be thrown further). They can be a pain, and you'll see in languages such as Scala that all exceptions are unchecked. That is, you don't explicitly have to handle them.
See this question/answer for more info.
You have to distinguish (and tell us clearly, so that we don't have to puzzle it out) between what the compiler is telling you and what happens at runtime.
In your case, without the try-catch the compiler was telling you that the read() might throw, and that you would have to deal with the exception somehow. That's what you did by adding the try-catch.
However, when you then ran the program, it didn't actually throw (and generally speaking, it's very unlikely that this program will throw), so it never entered the catch block.
This is because System.in.read() can throw IOException which is a checked Exception. And as mentioned in JLS 11.2.3 about checked exception:
It is a compile-time error if a method or constructor body can throw some exception class E when E is a checked exception class and E is not a subclass of some class declared in the throws clause of the method or constructor.
In one of my interview, they asked me, is it possible to write Throwable in catch() like this
try{
some code
}
catch(Throwable t)
{
}
I said yes. it will not give a compile time error but jvm would not handle it if there occur an Error(sub class of Throwable ), since Errors are irreversible conditions that can not be handled by jvm. than they further asked than what is the use of writing Throwable .
Please give me proper reply can we use Throwable in catch. if yes why.
It is possible to catch Throwable. And yes, you will also catch instances of java.lang.Error which is a problem when it comes to e.g. OutOfMemoryError's. In general I'd not catch Throwable's. If you have to, you should do it at the highest place of your call stack, e.g. the main method (you may want to catch it, log it, and rethrow it).
I agree with your argumentation, it does not make sense to catch events you're not able to handle (e.g. OutOfMemoryError). A nice post is here.
Yes it is possible to catch Throwable.
Whether the JVM / application will be able to continue if you catch an error depends on the actual error that occurred, what caused it, and what (if anything) your application does next.
In some cases, the JVM may be in such a bad way that no recovery is possible.
In some cases, the JVM is fine ... as long as you don't do certain things. Class loading errors are a good example. If your application doesn't attempt to use the class or dependent classes that you failed to load, you should be fine to continue. (In reality, applications are not designed to continue without classes that fail to load ... but if it was, it could.)
In some cases, the core JVM will be fine, but unspecified damage could have been done to the application's data structures, and/or to its threads and computation state. OOMEs are liable to do this to you, especially if your application is not designed to deal with threads that die unexpectedly.
Catching and recovering from OOMEs is problematic for another reason. While the termination of the current computation will free up some heap space, there's a good chance that it won't free up enough space. So you can easily get into a situation where your application is repeatedly throwing and catching lots of OOMEs, and making no real progress.
All of this means that it is generally a bad idea to try to recover from errors. And that's in line with what the javadoc for error says:
"An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch."
Yes we can catch Throwable but as best practice, it is not advised to catch Throwable.
Catching Throwable includes Errors too, we should not catch errors, it helps to identify JVM issues.
Throwable can be used instead of any individual exception/error. However it is recommended to pass through ThreadDeadException. So you can add extra catch clause for it, or filter by type.
Catching Throwable will catch all Exceptions (including RuntimeExceptions) and all Errors. It is not recommended to catch any of the parent Throwables (Throwable, Error, Exception or RuntimeException) but it is not uncommon to find this if a method throws too many checked exceptions or throws Exception.
It is not uncommon in certain APIs to document a method as throws Exception. This provides some flexibility at the expense of control. I like to define a new Exception class to handle this sort of case but that is personal preference.
The following simple class shows samples of the throwable types and corresponding catch blocks.
public class ThrowableExamples {
public static void main(String[] args) {
try {
// throw new NoSuchMethodException("Exception");
// throw new Exception("Exception");
// throw new IllegalStateException("RuntimeException");
// throw new RuntimeException("RuntimeException");
throw new NoSuchMethodError("Error");
// throw new Error("Error");
// throw new Throwable("Throwable");
} catch (RuntimeException e) {
System.out.println("Caught RuntimeException: " + (e.getMessage().equals("RuntimeException") ? "Expected" : "Unexpected"));
} catch (Exception e) {
System.out.println("Caught Exception: " + (e.getMessage().equals("Exception") ? "Expected" : "Unexpected"));
} catch (Error e) {
System.out.println("Caught Error: " + (e.getMessage().equals("Error") ? "Expected" : "Unexpected"));
} catch (Throwable e) {
System.out.println("Caught Throwable: " + (e.getMessage().equals("Throwable") ? "Expected" : "Unexpected"));
}
}
}