JDK-4428861 : java.lang.reflect.Method.invoke() throws incorrect exceptions
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Affected Version: 1.4.0
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS:
    generic,linux,solaris_2.6,solaris_7,solaris_8,windows_95,windows_2000 generic,linux,solaris_2.6,solaris_7,solaris_8,windows_95,windows_2000
  • CPU: generic,x86,sparc
  • Submitted: 2001-03-22
  • Updated: 2012-09-28
  • Resolved: 2001-04-10
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.0 betaFixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Description

Name: vrR10176			Date: 03/22/2001



Api spec says about method invoke (java.lang.reflect.Method):

"public Object invoke(Object obj, Object[] args)
               throws IllegalAccessException,
                      IllegalArgumentException,
                      InvocationTargetException
... skip ...
Control transfers to the invoked method. If the method completes 
abruptly by throwing an exception, the exception is placed in an 
InvocationTargetException and thrown in turn to the caller of invoke. 
... skip ...
Throws:
InvocationTargetException - if the underlying method throws an exception.
... skip ..."

And JVMS-2 says (chapter 2.16, Exceptions, p.40):
"Every exception is represented by an instance of the class Throwable 
or one of its subclasses"

Therefore, if the method completes abruptly by throwing LinkageError 
(for example NoSuchFieldError), this error should be placed in an 
InvocationTargetException and thrown in turn to the caller of invoke,
as this error is exception and subclass of Throwable. But JVM 
(jdk1.4.0beta-b54,b55,b56) does not place LinkageError to 
InvocationTargetException and throws it immediately. This is jdk 
regression, all previous jdk throws InvocationTargetException
instead of LinkageError.

The bug affects a lot of jck vm tests.

To reproduce the issue execute following test.
Compile first test.java and then test2.java
------------ test.java ------------------------
package invoke_test;

import java.lang.reflect.*;

abstract class testA{
	static int f;	
}

class test1 extends testA{
	static void run(){
		f = 2;
	}
}

public class test {
	public static void main(String args[]) {
		try {
			Class test_class = Class.forName("invoke_test.test1");
			Method runMethod = test_class.getDeclaredMethod("run", new Class[]{});
			Object ignore = runMethod.invoke(null, new Object[]{});
		} catch (InvocationTargetException e) {
			Throwable ee = e.getTargetException();
			System.out.println("Exception " + e + " wraps: " + ee);
			System.out.println("Test passed");
		} catch (Throwable e) {
			System.out.println("Failed with unexpected exception: " + e);
		}
	}
}
------------ test2.java ------------------------
package invoke_test;

abstract class testA{
}
------------ Logs -----------------------------

$ javac -d . test.java 

$ javac -d . test2.java 

$ java -version
java version "1.4.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta-b56)
Java HotSpot(TM) Client VM (build 1.4-beta-B56, mixed mode)

$ java -Xfuture invoke_test.test
Failed with unexpected exception: java.lang.NoSuchFieldError: f

------------ Logs , some previous jdks----------
----jdk1.4.0beta-b53----
$ java -version
java version "1.4.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta-b53)
Java HotSpot(TM) Client VM (build 1.4beta-B53, mixed mode)

$ java -Xfuture invoke_test.test
Exception java.lang.reflect.InvocationTargetException wraps: java.lang.NoSuchFieldError: f
Test passed

----jdk1.3.0fcsC----
$ java -version
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, interpreted mode)

$java -Xfuture invoke_test.test
Exception java.lang.reflect.InvocationTargetException wraps: java.lang.NoSuchFieldError: f
Test passed

----jdk1.2fcsV----
$ java -version
java version "1.2"
Classic VM (build JDK-1.2-V, green threads, sunwjit)

$ java -Xfuture invoke_test.test
Exception java.lang.reflect.InvocationTargetException wraps: java.lang.NoSuchFieldError: invoke_test.testA: field f not found
Test passed

-----------------------------------------------

======================================================================

Name: dkR10014			Date: 04/03/2001


This bug affects the following test from testbase_nsk:

   nsk/stress/except/except001

======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-beta FIXED IN: merlin-beta INTEGRATED IN: merlin-beta VERIFIED IN: merlin-beta3
14-06-2004

EVALUATION As noted by the submitter, the Method.invoke() specification states that all exceptions are wrapped in an InvocationTargetException. During the recent reflection rewrite (first present in b51) this was deliberately interpreted to mean "subclasses of java.lang.Exception" and later revised to "everything except java.lang.Errors" because of a feeling that it was a mistake from the beginning to silently squelch such errors as ThreadDeath and OutOfMemoryError. Unfortunately, this change in interpretation caused not only the indicated JCK tests to fail but also opened up the possibility that users' code which had once been robust with respect to exceptions or errors thrown during reflective invocations could now break. Peter.Jones@East and Rene.Schmidt@Eng both opined that such an incompatibility is unacceptable, and I have to agree. The implementations of reflective invocations (one in the VM and one in the libraries) have been modified to wrap all Throwables. NOTE that there has historically been a discrepancy in the exception-wrapping behavior of Class.newInstance() and Constructor.newInstance(): the version in Class used to allow all Throwables thrown in the constructor of the class to propagate out unchanged. This is clearly in violation of its specification and of the language as well, and was only possible because Class.newInstance() was implemented using native code. Now that Class.newInstance() is implemented in Java in terms of Constructor.newInstance(), it throws InstantiationException for all Throwables thrown inside constructors. This will affect a certain number of other JCK tests (see 4417941), but these tests must be declared as invalid and restructured. This fix will likely show up in build 58; if not, build 59. kenneth.russell@eng 2001-03-27 Jeff.Nisewanger@eng pointed out that Class.newInstance's propagaion of arbitrary checked exceptions was likely intentional, based on the Java Language Specification. Used a "magic" routine to allow propagation of any exceptions thrown in the constructor for this purpose. kenneth.russell@eng 2001-03-30 Fix is integrated in B59. As in pre-B51 Merlin builds and in all JDKs back to 1.1/1.0, Method.invoke() and Constructor.newInstance() wrap all Throwables in InvocationTargetException, and Class.newInstance() allows all Throwables (even checked exceptions) to propagate out unchanged. kenneth.russell@eng 2001-04-09
09-04-2001