I was trying to learn reflection and I came across this IllegalAccessException. Please see the following code:
public class ReflectionTest
{
public static void main(String[] args)
{
Set<String> myStr = new HashSet<String>();
myStr.add("obj1");
Iterator itr = myStr.iterator();
Method mtd = itr.getClass().getMethod("hasNext");
System.out.println(m.invoke(it));
}
}
When I tried to run this program, I got the following:
Exception in thread "main" IllegalAccessException
I don't understand what's going on. Any ideas? Thanks in advance.
The troublesome piece of code is this:
You probably wanted
hasNext
on theIterator
class. What you have written is theHashMap.KeyIterator
class, which according the Java language access specifiers (or at least the rough interpretation of JDK 1.0 used by reflection) is not available to your code.Use instead:
(And if it wasn't for learning purposes, stay away from reflection.)
I suspect you should use getDeclaredMethod (among other issues). I don't bother to remember Reflection API details (they're for the compiler!), but in your case compare your code with that produced by dp4j:
}
The only change you need to do is annotate your main method with @com.dp4j.Reflect:
NB: this works only with dp4j-1.2-SNAPSHOT (I've just added suport for it). If you don't use Maven, download the jar from here. You find the test case with your problem here.
It's apparent that your currently executing method does not have access to the method named
hasNext
, e.g., by it beingprivate
orprotected
. You could try to enable access to it usingmethod.setAccessible(true);
It might also be that you have some restrictions defined in your
security manager
(which, if you use e.g.,linux
, might have been included default from the distributions java package).[EDIT] As it turns out, Tom Hawtin identified the correct root cause. You are indeed operating on
HashMap.KeyIterator
. Although the solution would be to useIterator.class
instead ofitr.getClass()
you could still enable access to it usingsetAccessible(true)
.You need to suppress Java language access checking in order to reflectively invoke a private method in another class, with setAccessible(true):
Furthermore, when a SecurityManager is enable, we need extra permissions to call setAccessible(true). Otherwise, we get:
We only want to grant this suppressAccessChecks permission to trusted code source, definitely not to all classes in the call stack. So we would modify CallFoo.java:
You cannot access it, because the Iterator is a private inner class. More explanation can be found here.