Eclipse doesn't think System.exit interrupts execution - java

I've discovered an odd dichotomy in the way Eclipse reports the "The local variable may not have been initialized" error. This error normally occurs if I declare a variable outside a try/catch block, initialize it inside the try/catch block, and then use it after the try/catch block:
Random r;
try {
r = new AESCounterRNG();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
r.nextInt(); //Error: The local variable r may not have been initialized
This makes sense. I can avoid the error either by initializing the variable to null when I declare it, or by ensuring that the program's control flow never reaches the next statement if an exception occurs inside the try/catch block. Thus, in the case where I really can't continue executing if the variable initialization failed, I can do this:
Random r;
try {
r = new AESCounterRNG();
} catch (GeneralSecurityException e) {
throw new RuntimeException("Initialize secure random number generator failed");
}
r.nextInt(); //No error here
However, I recently tried using System.exit to stop the program instead of a RuntimeException to make my program's console output cleaner. I would think these are equivalent because both prevent the program from continuing execution, but I discovered that Eclipse does not agree:
Random r;
try {
r = new AESCounterRNG();
} catch (GeneralSecurityException e) {
System.err.println("Couldn't initialize secure random number generator");
System.exit(1);
}
r.nextInt(); //Error: The local variable r may not have been initialized
Why does Eclipse still give me the "not initialized" error when execution could never reach r.nextInt() if an exception occurred? Is this a bug in Eclipse, or is there some way that execution could continue to r.nextInt() even after calling System.exit?

Good question, it also bugged me several times.
The problem is that unlike throwing an exception, just calling a method (and that's what System.exit(1); is) does generally not guarantee that the program flow stops. Sure, the documentation of System.exit() says that this method never returns normally. But while the semantics of throw are defined by the language itself, the semantics of System.exit() are just in the Javadocs.
My guess is that they just didn't bother to implement this special case yet. While there is a bug report where this topic is touched (https://bugs.eclipse.org/bugs/show_bug.cgi?id=126551, see comment 2), it is marked as "wont fix" because it seems to be too complicated.
Edit: As rlegendi pointed out, it is actually a problem of the Java compiler, not just of Eclipse. My solution so far was to just go with the plain old throw, (instead of some special throw() method) which (in anything else than a very small application) is better than System.exit() anyway.

This isn't a bug: in your second example it is guaranteed that r is initialized at the call site (you throw an exeption otherwise so that execution branch is closed).
In the first and third example you simply execute program code and leave r undefined. If you assign null to it either at the exception handling block or at the declaration it won't complain.
Btw it is not an Eclipse issue, it is defined by the JLS that you cannot use an uninitialized variable. Try compiling it with Java and you should get the exactly same output.

Related

How is throw statement inside catch block preventing compiler error for uninitialized variable?

I am trying to figure out the inner workings of this code.
public void method() {
int x;
try {
x = 10;
} catch(Exception e) {
throw new RuntimeException(); //commenting out this line causes error
}
System.out.println("x: " + x);
}
When I comment out line 6, I get a compilation error on line 8 that x might have not been initialized. When I keep the throw statement inside the catch block, I get no such error. How does this make any difference? The way I see it, you can either initialize a variable inside a try block and use that value outside, or you cannot. At any rate, no exceptions are actually thrown because the catch block is never entered. Surely the mere possibility of an exception being thrown isn't causing the compiler to allow what would otherwise be a violation of Java syntax, right?
I can't speak to whether there are any real exceptions that could occur within the try – something like OutOfMemoryError might occur, but wouldn't be caught with catch (Exception e) – but I believe this is just due to the compiler being extra careful (perhaps unnecessarily so).
It isn't relevant that the line inside your try block doesn't throw an exception. Instead, it's evaluating that if an exception were to be thrown inside the try statement (somehow) and execution was subsequently allowed to continue past the catch clause, then x would be in an uninitialized state.
The exact answer is most likely buried in the Java Language Spec, possibly in 14.21. Unreachable Statements or 14.20.1. Execution of try-catch.
Looking at the simple code:
int x;
System.out.println(x);
The compiler detects that variable x may not have been initialized at the point where it is referenced, so it throws a compile error.
Now looking at your example, there are two paths the compiler can be sure about that code can take: Execute the try block or execute the catch block (with the latter, partial execution of the try block is possible as well). In this second case, the x variable will not be initialized and the compiler cannot generate sensible bytecode instructions. However, with the throws in the catch block, the execution of this code will stop and the usage of x is never reached, solving the uninitialized variable problem for the compiler.
To include another example that might be easier to understand:
int x;
if(someCondition()) {
x = 1;
} else {
// x is not initialized through this code path.
}
System.out.println(x); // x may be initialized here, but it is not guaranteed, so this causes a compile error.

Java - How to properly handle a try catch block

I was wondering what is the proper convention for handling a try/catch block. It is pretty obvious what should be within the try block but what about the catch block?
Can I write a message to the user like the following:
do {
try {
System.out.println("Pi to the number of decimal places:");
Scanner in = new Scanner(System.in);
userNth = in.nextInt();
} catch (Exception e) {
System.out.println("Error: Enter a number between 1 and 100");
}
} while(userNth < 1 || userNth > piDecimals);
Or is this bad practice?
Exception-handling is not the place to make rash assumptions; usually by the time this part of your code has been executed it's because something unanticipated has happened, this is when you want to be most careful to be accurate about detecting and recording what happened so that you can tell what needs fixing.
The choice of Exception as the type of exception that gets caught is too broad. The method you're calling throws 3 different exceptions for distinctly different reasons; only one of which is something that should be caught here. Also unchecked exceptions like NullPointerException will get caught by this. If you were to add some code to this catch block that inadvertently introduced a NPE it would be hard to figure out what went wrong. Your overbroad catch can result in bugs not being found or errors not getting handled properly.
(Btw Makoto makes a good point that nextInt isn't what you should be calling here anyway.)
Not logging the exception can be acceptable in narrow cases where you're certain of what the exception means (for instance, if you caught InputMismatchException, or NumberFormatException in Makoto's example code). But in combination with catching Exception it has the capacity to hide errors and cause confusion.
You likely chose to catch Exception because handling a bunch of different checked exceptions, most of which seemed unlikely to ever happen anyway, seemed like an intolerable nuisance. Providing a consistent way of handling and logging exceptions will help, by providing a reasonable default case for exceptions you don't know what to do with. That way if you see an exception you just can't handle, you always have the option of letting it be thrown (possibly catching it and wrapping it in an unchecked exception), knowing that if thrown it will get logged and end your program.
For a very small command-line program sometimes it's entirely ok to let exceptions that you can't handle be thrown from main (by adding throws Exception to the main method). This is ok for toy examples, small school projects, etc.; I'd only use it in production code if there was a plan for logging the output (like a batch file that redirects stderr to a file):
public static void main(String... args) throws Exception {
... application code
}
In most cases all the main method code should be placed in a try block where any Throwable is caught and logged:
public static void main(String... args) {
try {
... application code here
}
catch (Throwable t) {
logger.log(t);
}
}
Either alternative makes it less tempting for you to inappropriately swallow inconvenient checked exceptions.
Simple Answer: what you wrote is fine
Longer Answer: try-catch blocks are for executing code that may throw an exception, and then handling said exception if it occurs. In general, the catch block should have code that handles the exception however you need to handle it. If the statement you currently have is how you want to respond to an exception, then it's fine by convention. Some common things to do in a catch block are:
Throw another exception that encapsulates the thrown exception. (I often do this when parsing so that there can be a single ParseException)
Throw a runtime exception encapsulating the thrown exception and let java's default uncaught exception handler deal with it. (I do this a lot when I'm writing quick temporary programs and I don't want to deal with checked exceptions)
Pass it to some generic handler in your program, such as a GUI to display the error, etc.
call printStacktrace on it
But anything that fits your exception-handling needs is fine
In all actuality, this code is not going to function the way you intend it to. There are two key reasons for this:
nextInt() blocks until it receives an integer; that is, it's not going to care about what input you give it until it reads an integer, and
Even if this were to be okay, depending on how you initialize userNth and piDecimals, one or both of those variables may not be defined, thus preventing compilation.
Also, don't catch Exception. Be as specific as you can when catching exceptions, since Exception also includes some nifty and dangerous RuntimeExceptions like NullPointerException.
What you're looking to do:
Take in an integer input
If the user enters a non-integer, tell them they need to enter an integer
Keep doing this while userNth < 1 || userNth > piDecimals.
To that, we should look to get the right exception thrown by parsing the input as a string first, then as an Integer:
try {
System.out.println("Pi to the number of decimal places:");
userNth = Integer.parseInt(in.nextLine());
} catch (NumberFormatException e) {
System.out.println("Error: Enter a number between 1 and 100");
// You have to set this value to something so that userNth is defined!
userNth = Integer.MAX_VALUE;
}
The other part to this is that you have to decide what message you show if userNth > 1 && userNth < piDecimals, since your try...catch isn't going to cover that. This, I leave as an exercise for the reader.

What is the good practice to terminate program in catch clause

I have a method throws an Exception
public int myMethod throws Exception
I have another function calls myMethod function and hava try-catch block.
I throws a runtime exception to enforce the program to be terminated.
Is this a proper way to terminate the program? If I do this way, it prints the stack trace twice and the stack trace from RuntimeException is useless.
What is the suggested way to terminate program in catch clause with printing the full stack trace.
public int callMyMethod(){
try{
myMethod();
}
catch(Exception ex){
ex.printStackTrace(System.out);
throw new RuntimeException();
}
}
The answer is "it depends".
If this code is part of the application itself then calling System.exit(int) is possibly the best option. (But if the application is "failing", then you should call exit with a non-zero return code. Zero conventionally means "succeeded".)
However, if there is a significant possibility that this code is going to be embedded / reused in a larger Java application, calling System.exit(...) is problematic. For instance a library that calls System.exit(...) when something bad happens is going to cause havoc for an application that uses it.
For something like that, you might throw a custom runtime exception which you catch and handle specifically in your main method. (If I was doing that, I'd pass the Exception as a constructor parameter to the custom exception ... and make it the cause exception. And I wouldn't print it / log it at that point.)
(Calling System.exit(...) also causes problems when you are unit testing ... 'cos the call will most likely pull the plug on the JVM running the test suite!)
The other point is that catch (Exception ...) is almost always a BAD IDEA. The point is that this catches just about everything (including all sorts of things that you never dreamed could happen!) and buries them. It is far better to catch the specific exceptions you are expecting (e.g. checked exceptions) and can deal with ... and just let the rest propagate in the normal way.
If you are stuck with catch (Exception ...) because you are using something that is declared as throwing Exception, the best way to deal with it is to change the throws Exception. And the sooner the better. Change the throws Exception to declare a list of (more) specific exceptions that you expect to be thrown by the method.
public int callMyMethod(){
try{
myMethod();
}
catch(Exception ex){
ex.printStackTrace(System.out);
System.exit(0); // terminates with exit code 0, no extra stack trace.
}
}
Exception handling is one of the most important aspects in programming.
The answer for your question depends on what type of application you are working on.
system.exit(0) will just terminate your program and this can create a lot of havoc .
Also make sure that you never catch Exception , if you are doing that then you are catching all the types of exceptions which you may not intend to handle also.
Always catch Specific exception such that it gives you opportunity to handle it in a manner which you need.

Factoring out the finally {...} block

I wonder if the following two swnippest are semantically identical, and, if not, what are the differences (we assume that we want to compute a result of type R, and want to guard against exception X that may be thrown in the course of doing so):
public R tcf(....) {
try {
R some = ...;
... compute the result ....
return some;
}
catch (X exception) {
... exception handling ....
}
finally {
... clean up ....
}
}
and the following:
public R tc(....) {
try {
R some = ...;
... compute the result ....
return some;
}
catch (X exception) {
... exception handling ....
}
}
public R tf(....) {
try {
return tc(....); // wrap the try-catch in tc()
}
finally {
... clean up ....
}
}
As far as I can see, it boils down to if a try-catch block wrapped in a try block with finally is the same, semantically, as a try-catch-finally block, assuming that the code in the finally and catch phrases stays the same and the outer try block just promotes the result of the inner one.
Practical relevance: Given a code base that does not make use of try-catch-finally, when it should, and given that for some reason, one cannot toch that code, one could more or less mechanically generate a layer of wrapper methods that add the finally.
I am fully aware of the fact, that for many reasons, one should use the try ... catch ... finally whenever possible. Specifically, I am not suggesting in any way that one should refactor the first example so that it looks like the second.
Rather, I want to make sure that example 2 can safely be refactored to example 1.
Functionally, they are equivalent.
I think it's good style to perform cleanup in the same method that has allocated the resources in question. In some cases this is the only practical way to go about things (for example, if the cleanup involves variables that are local to tcf/tc).
Also, if tc doesn't clean up after itself, the cleanup becomes part of the function's contract, as a caller's obligation. This makes the design more error-prone, since the cleanup is easy to forget or get wrong. Additionally, if the steps involved in the cleanup in any way change, every single caller would need to be tracked down and updated.
Bottom line: if the cleanup can be performed in tcf, it should be.
They are the same, however. The try/finally should always be right after the recourse (that finally releases) is claimed. (note that this happens just before the try)
For example:
getLock();
try {
doSomething()
}
finally {
releaseLock();
}
Because it is really easy to forget to clean up, it should always happen at the same location as the taking of the resource. Reason for this is that you should never burden your callers with something they always have to do (and you can do yourself)
Not performing the finally in the same method as the try/catch leaves you open to the method doing the try/catch at some point being called without the finally being executed, which is likely a bug.
I'd therefore not advise you to write it like that, though in the scenario you describe, having to add functionality through a finally when the method containing the try/catch can't be modified, it's the only way.
I think your description is pretty accurate in that the tf finally will execute in both cases and that the exception handling will be dealt with in either tcf or tf catch block.
That is, in example (1): if an exception occurs in your try, flow will execute your catch block followed by your finally block. In example (2), in tc, if an exception occurs in your try block, flow will continue in your catch block and then (presuming the exception isn't re-thrown) return to the calling line in tf. On completion of your tf try block, flow will continue in your tf finally block.
I guess the main implication to be aware of, and that you may not be able to correct in the way you suggest, is that:
If you implement your code as in your second example, you won't be able to necessarily access the tc resources from tf to be able to clean them up.
Even if you can, you're cleaning up resources at a layer that is not close to the resource usage and may not even be used by other client code of the framework. I guess that's a question of documentation and training.
Both are identical. but finally is used when you are having a risk of breaking the function in between or want to release some resources held by the function. in that case catch is skipped but finally will definitely execute.
try can be used either with catch or finally or both. finally generally can't show the exception occurred but catch can trace the exception.

Java Try-Catch - how does it execute?

I am just wondering what the Java VM does with a Try-Catch. How does it execute it?
My best guess is that it is like a Linux system which when installing something does a test run and if no errors are found asks the user if he/she wants to proceed. In the case of a Try-Catch does it do a test run and if all is OK implement it?
It is much simpler than that - if any clause included in the try clause generates an error, the code in the catch clause (corresponding to that error - you can have multiple catch for a single try) will be executed. There is no way to know in advance if a particular clause will fail or not, only to try to recover after the error happens.
If you have ten clauses and the last one throws an error, the modifications performed by the first 9 will not be "reverted"!
try
{
//execute your code
}catch(Exception e)
{
//Log message
//IF you don't want to continue with the logic inside method, rethrow here.
}finally{
//Ir-respective of what the status is in above cases, execute this code.
}
//Continue with other logic in the method
.This is useful in cases where you want to determine part of your code need to be executed (or) not in exception case.
To understand more about how try-catch works in java read this tutorial.
The code which can give some unexpected result which the program can't handle is kept inside the try block,and to handle/catch the unexpected crashing of the program we use catch block.Where we declare type of Exception the code can throw
Eg:
int a;
try {
a=1/0;//program wil crash here
}catch(Exception e){
System.out.println("Division by zero ");//handling the crash here
}
It starts executing normally, w/o any checking. If any exception occurs, it will break out of the clause (like break in a loop), and immediately execute the catch, if no exception was found, it will skip the catch clause.
The finally clause, insures that it will be called no matter if an exception was thrown, or not. A practical example would be reading from a file or network, and close the streams, no matter if an exception was thrown or not.

Categories

Resources