...
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) { throw new IllegalArgumentException(); // Unchecked, no declaration required } 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")); } } |
...
This noncompliant code example attempts to catch undeclared checked exceptions thrown by Class.newInstance()
. It catches Exception
and dynamically checks whether the caught exception is an instance of the possible checked exception (carefully re-throwing rethrowing all other exceptions, of course), as shown below.
Code Block | ||
---|---|---|
| ||
public static void main(String[] args) { try { NewInstance.undeclaredThrow(new IOException("Any checked exception")); } catch(Exception e) { if (e instanceof IOException) { System.out.println("IOException occurred"); } else if (e instanceof RuntimeException) { throw (RuntimeException) e; } else { //some other unknown checked exception } } } |
This approach is fragile , because any unanticipated checked exception bypasses the dynamic check. See ERR14-J. Do not catch NullPointerException, RuntimeException, Exception, or Throwable for more details.
...
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) { throw new IllegalArgumentException(); // Unchecked, no declaration required } 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; } } |
Noncompliant Code Example (sun.misc.Unsafe
)
...
Classes that are loaded by the bootstrap class loader have the permissions needed to call the static
factory method Unsafe.getUnsafe()
. Arranging to have an arbitrary class loaded by the bootstrap class loader without modifying the sun.boot.class.path
system property can be difficult. However, an alternative way to gain access is to change the accessibility of the field that holds an instance of Unsafe
through the use of reflection. This works only when permitted by the current security manager (which would violate rule ENV04-J. Do not grant ReflectPermission with target suppressAccessChecks). ) Given access to Unsafe
, a call can throw an undeclared checked exception by calling the Unsafe.throwException()
method.
Code Block | ||
---|---|---|
| ||
import java.io.IOException;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class UnsafeCode {
public static void main(String[] args)
throws SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe u = (Unsafe) f.get(null);
u.throwException(new IOException("No need to declare this checked exception"));
}
}
|
Noncompliant Code Example (Generic
...
Exception)
An unchecked cast of a generic type with parametrized exception declaration can also result in unexpected checked exceptions. Any attempt to do so is diagnosed by the compiler, unless the warnings are suppressed.
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();
}
}
|
...
Note that Thread.stop()
is deprecated, and so this code also violates MET15-J. Do not use deprecated or obsolete classes or methods).
Noncompliant Code Example (Bytecode Manipulation)
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 also suffices. Similarly, a compiler other than {{javac}} might handle checked exceptions differently. Undeclared checked exceptions can also be produced through crafted use of the {{sun.corba.Bridge}} class. All these methods are strongly discouraged. |
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="2c4bb58536a6a27b-e7bed23f-4bcb42c8-aae7b86b-1b2d9bc6ac5a6ad2f92177ec"><ac:plain-text-body><![CDATA[ | [[MITRE 2009 | AA. Bibliography#MITRE 09]] | [CWE ID -703 | http://cwe.mitre.org/data/definitions/703.html] "Improper Check or Handling of Exceptional Conditions" | ]]></ac:plain-text-body></ac:structured-macro> |
| CWE ID -248 "Uncaught Exception" |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="deec672b625a246e-ee4ad821-46134c88-844096a0-76784ac419354bcbafe1cfc2"><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="7a090430da557547-456d90cd-4a7449b0-a6c0b99c-8196946097ec91c70eb45879"><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="7d0c926e7dfed86b-bf2d92e6-4971412f-ab2da49e-d8d3227607cb315f16ce0e12"><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="e2e7d0c28341cdb2-13a9df95-425d44d1-bdbbb7b0-64c0b7888d44c5eb28a0aa10"><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="3d22133326bb5a60-fd15356f-40444e24-8e18af40-4ee276928d127aad158e5fc8"><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="09284c93434c84c3-5bfe6767-433c42a5-a1bbae49-c2fa9f6c3deb9cdbe8d31a5f"><ac:plain-text-body><![CDATA[ | [[Venners 2003 | AA. Bibliography#Venners 03]] | "Scalability of Checked Exceptions" | ]]></ac:plain-text-body></ac:structured-macro> |
...