FULL PRODUCT VERSION :
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
(but seems to have been there since at least Java 6)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
In a nested try-catch an unreachable catch block is sometimes not found, it depends on the throws declaration in the exception throwing method.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
public class Buggy
{
// comment out one of those two lines
private void thrower() throws Exception
//private void thrower() throws SQLException
{
// some code so the throw may occur
throw new SQLException();
}
private void tester()
{
try
{
try
{
thrower();
}
catch (SQLException s)
{ // if throwser actually throws an SQLException, it is caught here
}
}
catch (SQLException s)
{ // this catch block can never be reached - that's the error - it's recognized if and only if thrower declares to throw SQLException, but no matter what thrower would actually throw or declare, this block can never be reached
}
catch (Exception e)
{ // maybe this will catch some RuntimeExceptions ...
}
}
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
So the outer catch-block for SQLException should always be marked as unreachable. Either an SQLException was thrown and caught in the inner catch-block for SQLException or it was not thrown.
The bug doesn't depend on SQLException, just anything derived from Exception will show this behaviour.
ACTUAL -
The outer catch-block for SQLException is marked as unreachable if and only if the thrower method declares to throw SQLException. If it declares to throw Exception the outer catch-block for SQLException is not marked as unreachable
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Unreachable catch block for SQLException. This exception is never thrown from the try statement body
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Buggy
{
// comment out one of those two lines
private void thrower() throws Exception
//private void thrower() throws SQLException
{
// some code so the throw may occur
throw new SQLException();
}
private void tester()
{
try
{
try
{
thrower();
}
catch (SQLException s)
{ // if throwser actually throws an SQLException, it is caught here
}
}
catch (SQLException s)
{ // this catch block can never be reached - that's the error - it's recognized if and only if thrower declares to throw SQLException, but no matter what thrower would actually throw or declare, this block can never be reached
}
catch (Exception e)
{ // maybe this will catch some RuntimeExceptions ...
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Remove the unreachable code - if found as unreachable.
The problem is when the throwing code comes from a library throwing SQLException and some others, the outer catch-block for SQLException won't be recognized as unreachable code.
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
(but seems to have been there since at least Java 6)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
In a nested try-catch an unreachable catch block is sometimes not found, it depends on the throws declaration in the exception throwing method.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
public class Buggy
{
// comment out one of those two lines
private void thrower() throws Exception
//private void thrower() throws SQLException
{
// some code so the throw may occur
throw new SQLException();
}
private void tester()
{
try
{
try
{
thrower();
}
catch (SQLException s)
{ // if throwser actually throws an SQLException, it is caught here
}
}
catch (SQLException s)
{ // this catch block can never be reached - that's the error - it's recognized if and only if thrower declares to throw SQLException, but no matter what thrower would actually throw or declare, this block can never be reached
}
catch (Exception e)
{ // maybe this will catch some RuntimeExceptions ...
}
}
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
So the outer catch-block for SQLException should always be marked as unreachable. Either an SQLException was thrown and caught in the inner catch-block for SQLException or it was not thrown.
The bug doesn't depend on SQLException, just anything derived from Exception will show this behaviour.
ACTUAL -
The outer catch-block for SQLException is marked as unreachable if and only if the thrower method declares to throw SQLException. If it declares to throw Exception the outer catch-block for SQLException is not marked as unreachable
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Unreachable catch block for SQLException. This exception is never thrown from the try statement body
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Buggy
{
// comment out one of those two lines
private void thrower() throws Exception
//private void thrower() throws SQLException
{
// some code so the throw may occur
throw new SQLException();
}
private void tester()
{
try
{
try
{
thrower();
}
catch (SQLException s)
{ // if throwser actually throws an SQLException, it is caught here
}
}
catch (SQLException s)
{ // this catch block can never be reached - that's the error - it's recognized if and only if thrower declares to throw SQLException, but no matter what thrower would actually throw or declare, this block can never be reached
}
catch (Exception e)
{ // maybe this will catch some RuntimeExceptions ...
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Remove the unreachable code - if found as unreachable.
The problem is when the throwing code comes from a library throwing SQLException and some others, the outer catch-block for SQLException won't be recognized as unreachable code.