Does anyone know why SonarQube detects a violation of the rule "Conditionally executed blocks should be reachable" (squid:S2583) in the following example? Is this a false positive?
In this piece of Java code, a file is read and an EOFException (or multiple of them) can occur in the process of reading the input stream. Thus, the exception is caught and handled, and a flag is set to remember that it happened. However, Sonar does not consider the line exHappened = true; in the first catch block and claims that variable is always false:
public static boolean doSomething() {
boolean exHappened = false;
try (DataInputStream s = new DataInputStream(new FileInputStream("test"))) {
LOGGER.info("Doing something...");
}
catch (EOFException eof) { // this Exception can definitely happen
exHappened = true;
}
catch (IOException io) {
LOGGER.error("sorry", io);
}
if (exHappened) { // Sonar thinks this condition is always false
return false;
}
else {
return true;
}
}
To make it even more clear, add a throw new EOFException() into the try { }, then the condition will always be true and Sonar still claims that it always false...
(I'm using SonarQube 5.6.6 and SonarJava plugin 4.13.0.11627)
This seems to be a problem in how catch blocks are handled during data flow analysis in SonarJava. Catch block catching subtype of the exception declared in the throws declaration of called method is not being considered, hence the assignment to the variable is never seen by the engine.
I created following ticket to fix this problem https://jira.sonarsource.com/browse/SONARJAVA-2483
Related
Here is the skeletal for the code:
flag1=True
flag2=True
do {
try {
if (){
throw new IllegalArgumentException();
}
.
.
.
do {
if () {
}
else {
}
.
.
.
if () {
}
} while (flag2);
flag1 = false;
} catch (RuntimeException ex) {
flag1 = true;
} catch (Exception ex) {
flag1 = true;
} catch (Error ex) {
flag1= true;
}
}
} while (flag1);
}
I am using junit4 for testing. I need to cover all the try catch blocks for testing as well.
I wrote a test case satisfying the first if condition and hence throwing illegal argument exception, but after throwing the exception the code moves to the do loop with flag1 always staying true.
To start off it sounds like you might be a Java beginner. If that's the case, let me suggest reading up on exception handling in Java. I think that will make it easy for you to understand the cause of this behavior. Here are some quick tutorials on that topic from Oracle: https://docs.oracle.com/javase/tutorial/essential/exceptions/
With that said, here is my explanation of what is causing the behavior you described: 1. flag1 remains true. 2. looping doesn't stop.
1.
The reason why flag1 is not set to true is that when IllegalArgumentException is thrown, all code between the place it is thrown and the exception catch blocks will be skipped. This includes skipping the line flag1 = false;.
2.
The reason the while loops do not exit when IllegalArgumentException is thrown is that IllegalArgumentException inherits from RuntimeException as you can see here: https://docs.oracle.com/javase/7/docs/api/java/lang/IllegalArgumentException.html . This means that your catch block catch (RuntimeException ex) will catch the thrown exception. Thus, what will happen is that the code in the RuntimeException catch block (retry = true;) will be executed and then the execution will continue from after the try-catch block. Since this is still inside the outer do-while loop, looping will continue.
I'm not familiar with java and I've been recently looking at some code written by some colleagues that's baffling me. Here's the gist of it:
public response newStuff(//random data inside) {
try {
response or = //gives it a value
log.info(or.toString());
return or;
}
catch ( Exception e) {
e.printStackTrace();
}
finally {
return null;
}
}
Is there really any point in adding a finally block here? Couldn't I just add the return null inside the catch block, which would execute the same behavior, or am I wrong?
Is there really any point in adding a finally block here?
The answer to this is a resounding "no": putting a return statement in the finally block is a very bad idea.
I just add the return null inside the catch block, which would execute the same behavior, or am I wrong?
It wouldn't match the original behavior, but that's a good thing, because it would fix it. Rather than returning null unconditionally the way the original code does, the code with the return inside the catch block would return null only on errors. In other words, the value returned in the try branch would be returned to the caller unless there is an exception.
Moreover, if you add return null after the catch block, you would see the correct effect of returning null on exception. I would go even further, and put a single return in the method, like this:
response or = null;
try {
or = //gives it a value
log.info(or.toString());
} catch ( Exception e) {
e.printStackTrace();
}
return or;
Actually, no. Finally is (nearly) always run, no matter what the result in the try-catch block; so this block always returns null. Here, look at this example:
public class Finally {
/**
* #param args
*/
public static void main(String[] args) {
System.out.println(finallyTester(true));
System.out.println(finallyTester(false));
}
public static String finallyTester(boolean succeed) {
try {
if(succeed) {
return "a";
} else {
throw new Exception("b");
}
} catch(Exception e) {
return "b";
} finally {
return "c";
}
}
}
It will print "c" both times.
The above mentioned exception to the rule would be if the thread itself is interrupted; e.g. by System.exit(). This is however a rare thing to happen.
The finally is always executed no matter what, and normally can be used to close sessions, etc.
Don't put returns inside a finally block.
This looks like a very bad practice. In this case your code will always return null.
The finally block is called last after the try-catch block runs. No matter if the try finished or the exception block was called. In this case, no matter which path of code is ran, you will always return null.
In the "normal" case where you put the return null after the finally there's indeed a chance to return something (either from the try or from the catch block) and if no flow yields a return object, you fall back to the return null, but you don't always return null.
I've read that a lot of people simply answer "don't use return in a finally block", without any explanation. Well, actually the code you posted is a good example where a return in a finally block is causing massive confusion. Even the, as of time of writing this, most upvoted answer, got it wrong. Your code will always execute the return null; as last command, even if there is an Exception.
But I can think of a situation where a return in a finally block actually makes sense. It appears to me that the goal of the author of your code was that the method never throws a Throwable, but returns null instead. This can actually be achieved if you modify the code like this:
public Result newStuff() {
Result res = null;
try {
res = someMethod();
log.info(res.toString());
}
catch (Exception e) {
e.printStackTrace();
}
finally {
return res;
}
}
But note that this will not call printStackTrace() on Errors and Throwables which are not Exceptions.
The "Finally" block will execute regardless of whether the "Catch" fires or not. So the behaviour is different than if you just put "return null" in the Catch block.
There should be no return statement in the finally block,remove return.
The need of finally block is where when you have such a code that should always be executed like you want to close your input stream or you want to close any connection etc.Just googled about this you will easily find the example for this.
In your case you are writing a method where you are returning something in try block and at the end you are writing finally block where you are returning null.I don't see any use of finally block here.
Finally block is used if you want to execute some statements even if code in try block or catch block generates an exception or not. But as you are using return in try block then there is no significance of putting a return in finally block. You can return directly from catch block and can remove finally block.
First understand why we need this three blocks in simple words for beginners.
1)try block: If you have doubt that your code will lead to an exception then put in try block
2)catch block: If exception arises then a piece of code you need to perform should be written in this block
3)finally block: If you want your piece of code to be executed no matters if exception arises or not then we go for finally block. Mainly this block is use for releasing resources.
For example:
try{
Connection conn=//something;
//some code for database operations
}catch(SQLException e){
e.printStackTrace()
}finally{
conn=null;
}
No matter what is result, you have to make connection as null because it is heavy object which if referenced will create load on database as only few connection objects are available.
Hence best way to keep them in finally block.
In your case, return null in finally block is bad approach as it will always return null although exception arises or not.
This question already has answers here:
Does a finally block always get executed in Java?
(51 answers)
Closed 9 years ago.
This is what I'm trying to do:
try {
//code
} catch (Exception e) {
return false;
} finally {
//close resources
}
Will this work? Is it bad practice? Would it be better doing this:
boolean inserted = true;
try {
//code
} catch (Exception e) {
inserted = false;
} finally {
//close resources
}
return inserted;
Yes, it will. The only things that can prevent a finally block to execute (AFAIR) are System.exit(), and an infinite loop (and a JVM crash, of course).
The finally block is executed always, unconditionally, as the last thing the try-catch-finally block does. Even if you execute Thread#stop against it, the finally block will still execute, just as if a regular exception ocurred.
Not just that, if you return from finally, that return value will trample over the return from either try or catch.
BTW Your first example is not just fine, but preferred. In the second example the reader must chase around the assignments to the variable, which is a tedious job and lets bugs slip through very easily.
Both are approximately the same. However, be careful with the following case:
int i = 0;
try
{
//code
}
catch(Exception e)
{
return i;
}
finally
{
i = 1;
}
0 is what will be returned.
I just wanted to add that it's described in the specs:
If the catch block completes abruptly for reason R, then the finally block is executed.
where of course
It can be seen, then, that a return statement always completes abruptly.
Should last statement be return in and non void return types method? But this is still working.
public String test()
{
try
{
// Do my work
return "myValue";
}
finally
{
System.out.println("I'm in Finally");
}
}
I'm bit lack of knowledge to understand how this work. Could someone explain me.
There is no problem with this code, because every possible path through it inevitably leads to a return statement*. It does not have to be the last statement textually, as long as it is the last statement logically (Java compiler is smart enough to figure out if it's so, and give you an error if there are paths through your code that do not return a value or throw an exception). The fact that there will be code executing after hitting the return (i.e. your finally block) does not change anything: as far as the compiler is concerned, your function has provided a return value before exiting the function.
* In fact, there is only one path through your function's code, and it terminates at the return statement.
It is sufficient in Java to make sure that all possible code paths either return a value or throw an exception. For example, the following code is valid:
public boolean test() {
if (3 < 5) {
return true;
} else {
throw new RuntimeException("Holy crap!");
}
}
In your example, your try block ends with a return, so the happy path is covered and there is no need for code beyond the finally; in addition, any exceptions thrown in the try will propagate out of the method and will have no chance to reach the end of the method, so all possible paths will never hit the section under the finally block and no return statement is needed. (In fact, a compiler may give you a warning or error about unreachable code if you added a return statement at the bottom!)
Things change when you add a catch clause, because now it's possible for code to flow beyond the try/catch/finally block:
public String test(){
try{
// Do my work
return "myValue";
}
catch (Exception ex) {
System.out.println("O noes something went wrong");
// swallow exception
}
finally {
System.out.println("I'm in Finally");
}
// Oh no! If an exception was caught, code can actually flow through here.
// Compiler will complain about a missing return statement until you add one.
// return "someOtherValue";
}
The key JLS concept for this is Normal and Abrupt Completion of Statements, combined with the behavior of try-finally.
The try block completes abruptly because of the return of "myValue". The finally block completes normally, so the whole try statement completes abruptly due to the same cause as the try block, return of "myValue".
In effect, the last statement in the method, the try statement, is one that returns a String.
In this case try and finally always execute. So, it doesn't matter where is return.
public String myfun(){
return "here";
}
or
public String myfun(){
try{
return "here";
}finally{
//will execute always
}
}
Are almost same. When, you see the flow of program. But, if there would be any conditional like
public String myfun(){
if(x==1){
return "here";
}
else{
// something here
}
}
In this case, it will raise error. Since, either any of the block will execute not both. Same as
public String fun(){
try{
return "here";
}
catch(Exception e){
//catch implementation without return
}
}
What happens to the return A code in my catch block?
public class TryCatchFinallyTest {
#Test
public void test_FinallyInvocation()
{
String returnString = this.returnString();
assertEquals("B", returnString);
}
String returnString()
{
try
{
throw new RuntimeException("");
}
catch (RuntimeException bogus)
{
System.out.println("A");
return "A";
}
finally
{
System.out.println("B");
return "B";
}
}
}
The finally get's executed right before any return's / exits from the method. Therefore, when you do
return "A";
it executes like so:
System.out.println("B");//Finally block
return "B";//Finally block
return "A";//Return from exception catch
And thus the "B" is returned, not the "A"
Maybe return "A"; is optimized away by the compiler, maybe not and "A" is just dynamically replaced. In fact it doesn't matter as you should not have this code.
This is one of the classical examples of problems with using finally for control flows : you lose some instructions and another coder might not see the "intent" (in fact it can only be a bug or a mischief).
You may have noted that javac issues a warning "finally block does not complete normally".
Don't return in a finally clause
the finally block will always be executed, while the catch block is only executed if there's an exception caught.
Finally
You can attach a finally-clause to a try-catch block. The code inside the finally clause will always be executed, even if an exception is thrown from within the try or catch block. If your code has a return statement inside the try or catch block, the code inside the finally-block will get executed before returning from the method.
References http://tutorials.jenkov.com/java-exception-handling/basic-try-catch-finally.html
Before return "A" , finally block would be called which will return "B" and your return "A" would be skipped and would never be executed. Its because finally block is always executed before return statement of the method, and if you are returning something from finally block then the return statement of your try/catch would always skipped.
Note : Returning from finally block is not a good practice for a Java programmer. JAVA Compiler also show you the warning as "finally block does not complete normally" if you are returning something from finally block.