-
CSR
-
Resolution: Unresolved
-
P4
-
None
-
minimal
-
Change to API notes and rewording involves minimal risk.
-
Java API
-
SE
Summary
Add API notes about Method.invoke
and Constructor.newInstance
wrapping all Error
in InvocationTargetException
, recommending users to unwrap and handle those errors or the consequences.
Problem
Method.invoke
and Constructor.newInstance
wraps Error
instances in InvocationTargetException
, which could be dangerous if OutOfMemoryError
or StackOverflowError
are wrapped; even further wrapping the InvocationTargetException into other throwables can lead to more errors from the VM, hiding the original error.
Meanwhile, the specifcations already require Error
instances to be wrapped in InvocationTargetException
, but the wording is not clear; it's easy for users to mishandle these APIs' InvocationTargetException
.
Solution
- Specify that
InvocationTargetException
wraps any throwable, explicitly. - Add a note section about this wrapping of
Error
and the risk associated to mishandling/ignoringError
.
Specification
diff --git a/src/java.base/share/classes/java/lang/reflect/Constructor.java b/src/java.base/share/classes/java/lang/reflect/Constructor.java
index 99f14d01536..e3656df0a4c 100644
--- a/src/java.base/share/classes/java/lang/reflect/Constructor.java
+++ b/src/java.base/share/classes/java/lang/reflect/Constructor.java
@@ -450,6 +450,15 @@ void specificToGenericStringHeader(StringBuilder sb) {
* <p>If the constructor completes normally, returns the newly
* created and initialized instance.
*
+ * @apiNote
+ * {@link Throwable}s thrown by the constructor, including {@link
+ * Error}s, are wrapped in {@link InvocationTargetException}s.
+ * The wrapped throwable should be handled; ignoring the wrapped
+ * throwable, such as passing the {@link InvocationTargetException}
+ * as the cause to construct a new throwable, may fail in cases
+ * like {@link OutOfMemoryError} or {@link StackOverflowError}.
+ * The JVM may throw new errors that hide the original ones.
+ *
* @param initargs array of objects to be passed as arguments to
* the constructor call; values of primitive types are wrapped in
* a wrapper object of the appropriate type (e.g. a {@code float}
@@ -471,7 +480,7 @@ void specificToGenericStringHeader(StringBuilder sb) {
* @throws InstantiationException if the class that declares the
* underlying constructor represents an abstract class.
* @throws InvocationTargetException if the underlying constructor
- * throws an exception.
+ * throws any {@link Throwable}.
* @throws ExceptionInInitializerError if the initialization provoked
* by this method fails.
*/
diff --git a/src/java.base/share/classes/java/lang/reflect/Method.java b/src/java.base/share/classes/java/lang/reflect/Method.java
index b6ccbaa8294..33711f9953d 100644
--- a/src/java.base/share/classes/java/lang/reflect/Method.java
+++ b/src/java.base/share/classes/java/lang/reflect/Method.java
@@ -526,6 +526,16 @@ void specificToGenericStringHeader(StringBuilder sb) {
* underlying method return type is void, the invocation returns
* null.
*
+ * @apiNote
+ * {@link Throwable}s thrown by the underlying method, including
+ * {@link Error}s like {@link AbstractMethodError}, are wrapped
+ * in {@link InvocationTargetException}s.
+ * The wrapped throwable should be handled; ignoring the wrapped
+ * throwable, such as passing the {@link InvocationTargetException}
+ * as the cause to construct a new throwable, may fail in cases
+ * like {@link OutOfMemoryError} or {@link StackOverflowError}.
+ * The JVM may throw new errors that hide the original ones.
+ *
* @param obj the object the underlying method is invoked from
* @param args the arguments used for the method call
* @return the result of dispatching the method represented by
@@ -546,7 +556,7 @@ void specificToGenericStringHeader(StringBuilder sb) {
* cannot be converted to the corresponding formal
* parameter type by a method invocation conversion.
* @throws InvocationTargetException if the underlying method
- * throws an exception.
+ * throws any {@link Throwable}.
* @throws NullPointerException if the specified object is null
* and the method is an instance method.
* @throws ExceptionInInitializerError if the initialization
- csr of
-
JDK-8335478 Add notes for Error handling in Method.invoke and Constructor.newInstance
-
- Open
-