Hi there,
this is the bug report I just placed with Sun (thanks to Noel to
pointing me to Bug parade!), so you can see for yourself the problem
(having an object in hand and not being able to invoking public methods
on it via reflection) in case you are interested.
---rony
-------- Original Message --------
Subject: Your Report: IllegalAccessException in Method.invoke(...) for a
public method of an object be
Date: Thu, 13 Feb 2003 16:15:02 -0700 (MST)
From: "[EMAIL PROTECTED]" <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED]
************************************************
Your report has been assigned an internal review ID of: 181276
This review ID is NOT visible on the "Java Developer Connection" (JDC).
We greatly appreciate your interest in improving the quality
of Java(tm) Technology from Sun Microsystems.
Please be aware that the large volume of reports we receive
sometimes prevents us from responding individually to each
message.
We currently have a three week response time for responding to
Bug Reports. If the information is determined to be a new bug,
or a duplicate of a known bug, you will receive a followup email
containing a seven digit bug number. You may search for this bug
number on the "Java Developer Connection" (JDC) at this URL:
http://developer.java.sun.com/developer/bugParade/index.html.
If you just reported an issue that could have a major
impact on your project and you require a response,
please consider purchasing one of the support offerings
at this URL:
http://java.sun.com/support/index.html
------------------------------------------------------
dateCreated: Thu Feb 13 16:15:00 MST 2003
type: bug
cust_name: Rony G. Flatscher
cust_email: [EMAIL PROTECTED]
jdcid: flatscher
status: Waiting
category: java
subcategory: classes_lang
company: Wirtschaftsuniversita"t Wien
release: 1.4
hardware: x86
OSversion: win_xp
priority: 4
synopsis: IllegalAccessException in Method.invoke(...) for a public method of an object be
description: FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)
-- and also occurring on --
java version "1.3.1_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_06-b01)
Java HotSpot(TM) Client VM (build 1.3.1_06-b01, mixed mode)
-- and also occurring on --
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)
-- and also occurring on --
java version "1.1.8"
FULL OPERATING SYSTEM VERSION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
(YES, I DID read the bug database on "IllegalAccessException"!)
1) Using an object of an inner class, which defines public
methods cannot be invoked via "Method.invoke(...)", *if*
used from a class not belonging to the package.
2) The public methods of the very same object *can* be used
from a class not belonging to the package, if not using
reflection.
3) Studying the language specification, either the compiler
*and* reflection allow usage of public members of inner
classes (e.g. if the object was returned by getter method),
or *both* do not allow for it, irrespectible of whether the
using class belongs to the same package or not.
To make this more understandable: if one receives an object
with e.g. the Enumeration interface implemented for it, then
one needs to be able to use those public methods. This is
the case, if one uses e.g. Hashtable (or the subclass
Properties) and wishes to enumerate the keys. Now, this
works for compiled Java programs, but using reflection
instead, does *not* work, but throws
"IllegalAccessException" instead. Obviously, if the compiler
does not cause that exception invoking the same public
methods via Method.invoke(...) must not throw that exception
either.
Hence the classification of a bug for this inconsistent
behaviour.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. compile the three enclosed (short) programs, note that
two of them (RgfCase.java and RgfUseCase1.java) belong
to the same package "rgfTest" (so they should reside
in such a subdirectory)
2. the third program "RgfUseCase2.java" is *exactly*
the same program as "RgfUseCase1.java", but with no
package statement (hence this class does not belong
to the above package)
3. make sure that the compiled Java programs of "rgfTest"
package are retrievable and enter:
java RgfUseCase1
You see that using both, the compiled and the reflection
version of accessing the public methods of the received
object of the inner class in "RgfCase.java" work.
4. make sure that the compiled Java programs of "rgfTest"
package are retrievable and enter:
java RgfUseCase2
You see, that *only* the compiled version works without
a problem, but not the reflection version of accessing
the public methods of the received object of the inner
class in "RgfCase.java" work.
Either both in 4.) should work or none!
(Again, I did not find a place in the Java specification
where the contrary would be stated explicitly or implicitly.)
EXPECTED VERSUS ACTUAL BEHAVIOR :
- Expected results: if using reflection to invoke methods at
runtime, by default all methods should be invocable that can
be invoked with a compiled version.
Hence, it should be possible to invoke public methods on
received (and hence accessible!) objects via reflection, for
which implementors arbitrarily used inner classes (e.g. to
distinguish the implementation of interfaces from the outer
class as is the case e.g. Hashtable and Hashtable@Enumerator).
- Actual Results: whenever one invokes a *PUBLIC* method on
a received object, which is an instance of an inner class,
erroneously the "IllegalAccessException" is thrown!
ERROR MESSAGES/STACK TRACES THAT OCCUR :
As you can see,
1) the correct method is found (see signature),
2) the exception is raised by Method.invoke(), which is a native method.
-------------------- cut here -----------------------
9/14: [hasMoreElements]
bean=[java.util.Hashtable$Enumerator@c23c12], args=[[Ljava.lang.Object;@c23de8],
m=[public boolean java.util.Hashtable$Enumerator.hasMoreElements()]
EngineUtils: in last catch:
e=java.lang.IllegalAccessException: java/util/Hashtable$Enumerator
EngineUtils: trace stack:
- - - - - - - - - - - -
java.lang.IllegalAccessException: java/util/Hashtable$Enumerator
at java.lang.reflect.Method.invoke(Native Method)
at com.ibm.bsf.util.EngineUtils.callBeanMethod(EngineUtils.java:160)
at com.ibm.bsf.engines.rexx.RexxAndJava.javaCallBSF(RexxAndJava.java:1339)
- - - - - - - - - - - -
com.ibm.bsf.BSFException: method invocation failed: java.lang.IllegalAccessExcep
tion: java/util/Hashtable$Enumerator
at com.ibm.bsf.util.EngineUtils.callBeanMethod(EngineUtils.java:170)
at com.ibm.bsf.engines.rexx.RexxAndJava.javaCallBSF(RexxAndJava.java:1339)
"invoke": got exception [method invocation failed:
java.lang.IllegalAccessException: java/util/Hashtable$Enumerator].
Exception in thread "main" com.ibm.bsf.BSFException: "invoke": object
'java.util.Hashtable$Enumerator@c23c12' - method [hasMoreElements], method not
found!
at com.ibm.bsf.engines.rexx.RexxAndJava.javaCallBSF(RexxAndJava.java:1349)
263 *-* call BSF "invoke", "java.util.Hashtable$Enumerator@c23c12",
"HASMOREELEMENTS"
263 *-* interpret code -- execute this dynamically created Rexx string
9 *-* do while enum~hasMoreElements -- loop over enumeration
Error 40 running e:\rony\dev\bsf\bsf-2_2\lib\com\ibm\bsf\engines\rexx\BSF.cls
line 263: Incorrect call to routine
Error 40.1: External routine "BSF" failed
-------------------- cut here -----------------------
The documentation of Method.invoke() states that: "If this Method object
enforces Java language access control and the underlying method is inaccessible,
the invocation throws an IllegalAccessException."
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
----------------- cut here -----------------
// [EMAIL PROTECTED], Wirtschaftsuniversitaet Wien/Universitaet
Augsburg, 2003-02-13
package rgfTest;
public class RgfCase
{
String [] info=null;
int myCount=2;
public RgfCase()
{
info=new String[myCount];
info[0]="Hi, there.";
info[1]="How do we do, today?";
}
public String toString ()
{
String t="";
for (int i=0; i< obj.myCount; }
public Object nextElement() { return obj.info[count++]; }
}
}
----------------- cut here -----------------
----------------- cut here -----------------
// [EMAIL PROTECTED], Wirtschaftsuniversitaet Wien/Universitaet
Augsburg, 2003-02-13
package rgfTest;
public class RgfUseCase1 // same package as "RgfTest"
{
public static void main (String args[]) {
rgfTest.RgfCase r=new rgfTest.RgfCase(); // create an instance
System.out.println("r.toString=["+r+"]");
java.util.Enumeration e=r.getEnumeration();
System.out.println("\nNow using an enumeration:");
while (e.hasMoreElements()) {
System.out.println("\t"+e.nextElement());
}
System.out.println("\nNow using reflection to access a public method of
the inner class:");
Class ec=e.getClass();
java.lang.reflect.Method [] em=ec.getMethods(); // get the inner class
methods
int i;
Object o;
for (i=0; i
