problem with class accessiblity check in invoke (natMethod.cc)

Erik Groeneveld erik@cq2.nl
Wed Dec 23 18:09:00 GMT 2009


On Wed, Dec 23, 2009 at 17:44, Bryce McKinlay <bmckinlay@gmail.com> wrote:
> On Wed, Dec 23, 2009 at 3:58 PM, Erik J Groeneveld <erik@cq2.nl> wrote:
[...]

> In your example, you aren't testing the accessibility of Iterator, but
> rather that of the class which is returned by ArrayList.iterator(),
> which is indeed a package-private class from a different package!

That is true. But the code that uses invoke is generic.  It calls a
given method on a given object:

java::lang::Object* callMethod(java::lang::Object* target,
java::lang::String* methodname)

It cannot do anything else than trying to find the method using the
java::lang::Object pointer that has been passed to it.  And it cannot
tell from this pointer that the actual reference the application is
using is of type Iterator (or any other interface for that matter).
This is something the compiler can work out, but not the runtime.
Indeed this works:

    java::util::ArrayList* l = new java::util::ArrayList();
    java::util::Iterator* i = l->iterator();
    i = l->iterator();
    i->hasNext();

But the fix below only works for the example I made up because a human
can tell the reference is of type Iterator:

> Another fix for your code would be to change:
>
>   java::lang::reflect::Method* m = i->getClass()->getDeclaredMethod(
>           JvNewStringUTF("hasNext"), NULL);
>
> to something like:
>
>   java::lang::reflect::Method* m =
> &(java::util::Iterator::class$)->getDeclaredMethod(
>              JvNewStringUTF("hasNext"), NULL);

So I wonder how the rules from 6.6 in the Java Language Specification
can be implemented properly when the type of the reference is not
known to invoke.  Because the relevant part of the spec speaks about
"members of a reference".

"A member (class, interface, 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: ..."

but invoke simply does not know the reference, and cannot get it from
the Java call stack either (hence the core dump).  All it knows is the
actual object, and this object is of a type that is not accessible,
although it implements an interface that is accessible.

Is there a more gentle solution other than calling setAccessible() on
the method object? (which works)  Could it be done in GCJ?

Erik



More information about the Java mailing list