Java requires that each method address every checked exception that can be thrown during its execution either by handling the exception within a try-catch
block or by declaring that the exception can propagate out of the method (via the throws
clause). Unfortunately, there are a few techniques that permit undeclared checked exceptions to be thrown at runtime. Such techniques foil defeat the ability of caller methods to use the throws
clause to determine the complete set of checked exceptions that could propagate from an invoked method. Consequently such techniques must not be used to throw undeclared checked exceptions.
Noncompliant Code Example (Class.newInstance()
)
This noncompliant code example throws undeclared checked exceptions. The undeclaredThrow() method takes a Throwable argument, and invokes a function that will throw the argument without declaring it. While undeclaredThrow() catches any exceptions the function declares that it might throw, it nevertheless throws the argument it is given without regard to whether the argument is one of the declared exceptions. This noncompliant code example also violates rule ERR07-J. Do not throw RuntimeException, Exception, or Throwable. However, because of exception ERR08-EX0, it does not violate rule ERR08-J. Do not catch NullPointerException or any of its ancestors.
Any checked exception thrown by the default constructor of java.lang.Class.newInstance()
is propagated to the caller, even though Class.newInstance()
declares that it throws only InstantiationException
and IllegalAccessException
. This noncompliant code example demonstrates one way to use Class.newInstance()
to throw arbitrary checked and unchecked exceptions.This noncompliant
Code Block |
---|
...
Code Block | ||
---|---|---|
| ||
public class NewInstance { private static Throwable throwable; private NewInstance() throws Throwable { throw throwable; } public static synchronized void undeclaredThrow(Throwable throwable) { // These exceptions should not be passed if (throwable instanceof IllegalAccessException || throwable instanceof InstantiationException) { // Unchecked, no declaration required throw new IllegalArgumentException(); } NewInstance.throwable = throwable; try { // next line throws the Throwable argument passed in above, // even though the throws clause of class.newInstance fails // to declare that this may happen NewInstance.class.newInstance(); } catch (InstantiationException e) { /* unreachable */ } catch (IllegalAccessException e) { /* unreachable */ } finally { // Avoid memory leak NewInstance.throwable = null; } } } public class UndeclaredException { public static void main(String[] args) { // No declared checked exceptions NewInstance.undeclaredThrow( new Exception("Any checked exception")); } } |
...
Code Block | ||
---|---|---|
| ||
public static synchronized void undeclaredThrow(Throwable throwable) { // These exceptions should not be passed if (throwable instanceof IllegalAccessException || throwable instanceof InstantiationException || throwable instanceof NoSuchMethodException || throwable instanceof InvocationTargetException) { // Unchecked, no declaration required throw new IllegalArgumentException(); } NewInstance.throwable = throwable; try { Constructor constructor = NewInstance.class.getConstructor( new Class<?>[0] ); constructor.newInstance(); } catch (InstantiationException e) { /* unreachable */ } catch (NoSuchMethodException e) { /* unreachable */ } catch (IllegalAccessException e) { /* unreachable */ } catch (InvocationTargetException e) { System.out.println("Exception thrown: " + e.getCause().toString()); } finally { // Avoid memory leak NewInstance.throwable = null; } } |
...
Code Block | ||
---|---|---|
| ||
interface Thr<EXC extends Exception> { void fn() throws EXC; } public class UndeclaredGen { static void undeclaredThrow() throws RuntimeException { @SuppressWarnings("unchecked") // Suppresses warnings Thr<RuntimeException> thr = (Thr<RuntimeException>)(Thr) new Thr<IOException>() { public void fn() throws IOException { throw new IOException(); } }; thr.fn(); } public static void main(String[] args) { undeclaredThrow(); } } |
Noncompliant Code Example (Thread.stop({{Throwable
)}})
Wiki Markup |
---|
According to the Java API \[[API 2006|AA. Bibliography#API 06]\], class {{Thread}}: |
...
Code Block | ||
---|---|---|
| ||
static void sneakyThrow(Throwable t) { Thread.currentThread().stop(t); } |
Note that Thread.stop()
is are deprecated, so this code also violates rule MET02-J. Do not use deprecated or obsolete classes or methods.
...
Wiki Markup |
---|
It is also possible to disassemble a class, remove any declared checked exceptions, and reassemble the class so that checked exceptions are thrown at runtime when the class is used \[[Roubtsov 2003|AA. Bibliography#Roubtsov 03]\]. Compiling against a class that declares the checked exception and supplying at runtime a class that lacks the declaration can also suffices.result Similarly, a compiler other than {{javac}} might handle in undeclared checked exceptions differently. Undeclared checked exceptions can also be produced through crafted use of the {{sun.corba.Bridge}} class. All these methodspractices are violations of stronglythis discouragedrule. |
Risk Assessment
Failure to document undeclared checked exceptions can result in checked exceptions that the caller is unprepared to handle, consequently violating the safety property.
...
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="88b7544b59af5828-dab7e15f-41004594-a20da13a-09b8ba981ea4d2497490b37e"><ac:plain-text-body><![CDATA[ | [[Bloch 2008 | AA. Bibliography#Bloch 08]] | Item 2. Consider a builder when faced with many constructor parameters | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="2abfebdd852d73aa-e27dcf7e-4b814e8f-9975b8b9-c0b4c6c019cfe64e37eecbe6"><ac:plain-text-body><![CDATA[ | [[Goetz 2004b | AA. Bibliography#Goetz 04b]] |
| ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="59de684be52ac4c2-34ff3087-4fa74be7-8e089131-700832d25afbdd1f10faf5ef"><ac:plain-text-body><![CDATA[ | [[JLS 2005 | AA. Bibliography#JLS 05]] | Chapter 11, Exceptions | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="282f0ea0c6dc0ffe-b9667503-45c94c8a-aa54a9d7-cc2fbbfbf3750f4abb1f98a5"><ac:plain-text-body><![CDATA[ | [[Roubtsov 2003 | AA. Bibliography#Roubtsov 03]] |
| ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="9fd6cbb832e0b326-778ecfa0-45d547ef-acf3ae02-392e49b67fbc701a17d00ee1"><ac:plain-text-body><![CDATA[ | [[Schwarz 2004 | AA. Bibliography#Schwarz 04]] |
| ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="fc8bac72805f87eb-29d08fe8-4041475a-a47f8241-cf9b4f4c6e5acbbc8a094443"><ac:plain-text-body><![CDATA[ | [[Venners 2003 | AA. Bibliography#Venners 03]] | Scalability of Checked Exceptions | ]]></ac:plain-text-body></ac:structured-macro> |
...