Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IllegalAccessException when using call dynamic methods

I am trying to use Reflection in Java but I am getting a weird error. What are the possible issues when I get an error that says:

java.lang.IllegalAccessException: Class com.myapp.core.utils.EventDispatcher can not access a member of class appApp$1 with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)

I just trying to create my own EventDispatcher class and inside it, the part that I used reflection, which is also the line of code that causes the problem is:

public void dispatchEvent(Event e, String callMethName) {
IEventListener list = ((IEventListener)listeners[i]);
                list.getClass().getMethod(callMethName, Event.class).invoke(list, e);
}

On my main class, I have something that calls addListener which will just add the listener into a list in the EventDispatcher class this way:

try {
obj.addListener("onTestHandler", new MyTestEventListener(){
    @Override
    public void onTestHandler(Event e) {
        System.out.println("hello!");
    }
});
} catch (SecurityException e) {
    e.printStackTrace();
}

So the first parameter that says "onTestHandler" will pass into the EventDispatcher class and eventually as part of the parameter callMethName in the dispatchEvent method, which will call the method dynamically.

The passing of methods and everything is correct. It is the part that has the reflection somehow has problems. It seems to be able to find the method. But for some reason, throws an IllegalAccessException and cannot call the method.

Why is it like this?

Thanks.

like image 676
Carven Avatar asked May 28 '11 12:05

Carven


1 Answers

I suspect that the anonymous class (appApp$1) that implements MyTestEventListener has package visibility and that the reflection code is in another package.

For this code:

package foo.p1;
public class Target {
  public static interface Foo {
    public void bar();
  }

  public static Foo newFoo() {
    return new Foo() {
      @Override
      public void bar() { 
      }
    };
  }
}

This code will fail because the runtime type returned by newFoo() is not a public class:

package foo.p2;
import foo.p1.Target;
public class Main {
  public static void main(String[] args) throws Exception {
    Target.Foo foo = Target.newFoo();
    foo.getClass()
        .getMethod("bar")
        .invoke(foo);
  }
}

This can be overcome by setting the method as accessible:

Target.Foo foo = Target.newFoo();
Method m = foo.getClass()
    .getMethod("bar");
m.setAccessible(true);
m.invoke(foo);

Or by using the method from the public interface:

Target.Foo foo = Target.newFoo();
Target.Foo.class.getMethod("bar")
    .invoke(foo);
like image 111
McDowell Avatar answered Oct 11 '22 05:10

McDowell