On Sun, 2007-04-08 at 12:53 +0200, Christian Thalinger wrote: > Grrr, I hate this access checks. I'll try to fix that _again_. This seems to be pretty subtle and we found multiple runtimes (jamvm, cacao, gcj and kaffe at least) that seem to get this wrong. And the online documentation is not very precise. As it says just: "throws IllegalAccessException - if this Method object enforces Java language access control and the underlying method is inaccessible." But the JCL (second edition, volume 1) is more precise: "When invoke() is called, the JVM performs the access checks described in the JLS, First Edition, Section 6.6.1. These checks compare the identity of the caller of invoke() with the access permission and identity of the method being called. It is as if the caller of invoke() had a staticly compiled call to the selected method. the access cgecks take into account both the accessibility of the method itself and the accessibility of its class." And JLS, First Edition, Section 6.6.1 says: "If a class or interface type is declared public, then it may be accessed by any Java code that can access the package in which it is declared. If a class or interface type is not declared public, then it may be accessed only from within the package in which it is declared. A member (field or method) of a reference (class, interface, or array) type or a constructor of a class type is accessible only if the type is accessible and the member or constructor is declared to permit access: [...]" So when Method.invoke() is called on an method member of an object which class type isn't public then it should only be allowed to successfully call the method if the caller is in the same package. Attached is a simplified test case (3 classes - c1 is in package p1, c2 and c3 are in package p2, c2 is not public, p1.c1 is the entry point) that should throw an IllegalAccessException on the line: m.invoke(o, new Object[0]); Cheers, Mark
package p1; import java.lang.reflect.Method; public class c1 { public static void main(String[] args) throws Exception { Object o = p2.c3.getc2(); Class c = o.getClass(); Method m = c.getDeclaredMethod("m", new Class[0]); m.invoke(o, new Object[0]); } }
package p2; // package private class class c2 { public void m() { } }
package p2; public class c3 { public static Object getc2() { return new c2(); } }