Re: problem with class accessiblity check in invoke (natMethod.cc)
Andrew Haley <[email protected]>
| Newsgroups | gmane.comp.gcc.java.devel |
|---|---|
| Message-ID | <[email protected]> |
On 12/23/2009 06:09 PM, Erik Groeneveld wrote: > On Wed, Dec 23, 2009 at 17:44, Bryce McKinlay <[email protected]> wrote: >> On Wed, Dec 23, 2009 at 3:58 PM, Erik J Groeneveld <[email protected]> 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(); Right, because CNI is bypassing the controls. > 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? I can't see any good reason why there should be. Unless the method is marked accessible, java.lang.reflect.Method.invoke has to check the class of the caller. There should not be a segfault, true, but an IllegalAccessException wouldn't be unreasonable. That's what this code does: import java.lang.reflect.*; import java.util.*; public class Problem { public static void main(String[] args) throws Throwable { ArrayList l = new ArrayList(); Iterator i = l.iterator(); Method m = (i.getClass().getDeclaredMethod ("hasNext", null)); m.invoke(i, null); } } Andrew.