Reducing "exception is never thrown in body of corresponding try statement" Error to a Warning

Mike Duigou openjdk at duigou.org
Sun Oct 20 22:36:42 UTC 2019


Hello all;

As part of my Oracle CodeOne talk "Exceptions 2020" I made two proposals 
for improving Java exceptions. One of the proposals was to remove the 
compile time error produced when and exception is caught that is not 
thrown by the enclosed statements. Specifically I am proposing the 
removal of the following section from JLS 11.2.3

     "It is a compile-time error if a catch clause can catch checked 
exception class E1
      and it is not the case that the try block corresponding to the 
catch clause can
      throw a checked exception class that is a subclass or superclass of 
E1, unless E1
      is Exception or a superclass of Exception."

The advantage of removal of this rule is that removal allows API authors 
to better document the actual exceptions thrown by constructors and 
methods. Vestigial or inaccurate throws specifications can be eliminated 
without "breaking" calling code. This makes it easier to evolve the API 
by narrowing (including to empty), the exception specification of method 
without impacting existing code which uses the API.

To allow application authors to clean up dead code an equivalent warning 
would still be provided and probably should be encouraged by the JLS 
specification. The warning would alert them that the catch clause will 
not be executed.

As an API author I have been frustrated many times by being unable to 
reduce or remove a method's exception specification without causing 
compatibility issues for my users and I have also been frustrated when 
libraries did choose to alter their method exception specifications and 
"broke" my code which caught the no longer thrown exceptions. Does this 
seem like a feature/change worth pursuing?

Cheers,

Mike

The changes to javac needed to accomplish this change are quite simple:

diff --git 
a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java 
b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
index 0c1fead9a4..f7793d0605 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
@@ -1271,7 +1277,7 @@ public class Flow {
              } else if (!chk.isUnchecked(pos, exc) &&
                      !isExceptionOrThrowable(exc) &&
                      !chk.intersects(exc, thrownInTry)) {
-                log.error(pos, Errors.ExceptNeverThrownInTry(exc));
+                log.warning(pos, Warnings.ExceptNeverThrownInTry(exc));
              } else {
                  List<Type> catchableThrownTypes = 
chk.intersect(List.of(exc), thrownInTry);
                  // 'catchableThrownTypes' cannnot possibly be empty - 
if 'exc' was an
diff --git 
a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties 
b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
index 1f29df0704..e29b5583e4 100644
--- 
a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ 
b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -533,10 +533,6 @@ compiler.err.error.reading.file=\
  compiler.err.except.already.caught=\
      exception {0} has already been caught

-# 0: type
-compiler.err.except.never.thrown.in.try=\
-    exception {0} is never thrown in body of corresponding try 
statement
-
  # 0: symbol
  compiler.err.final.parameter.may.not.be.assigned=\
      final parameter {0} may not be assigned
@@ -2019,6 +2015,14 @@ compiler.warn.unchecked.generic.array.creation=\
  compiler.warn.unchecked.varargs.non.reifiable.type=\
      Possible heap pollution from parameterized vararg type {0}

+# 0: type
+compiler.warn.except.never.thrown.in.try=\
+    exception {0} is never thrown in body of corresponding try 
statement
+
  # 0: symbol
  compiler.warn.varargs.unsafe.use.varargs.param=\
      Varargs method could cause heap pollution from non-reifiable 
varargs parameter {0}


More information about the jdk-dev mailing list