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(); }
}

Reply via email to