1

I am getting following exception when calling a method using java reflection,

Let's say that I have follwing classes,

package hello;

public class SimpleService {

    public void SayHello(){
        System.out.println("Hello World!");
    }
}

and this class is compressed into a jar file called hello.jar

then I am calling the SayHello() from another class in another jar called TestHello.jar which is a simple Swing application.

public class TestPanel extends javax.swing.JPanel{

.
.

jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
});

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        try {
            String jarPath = "/SayHello/SayHello" + ".jar";            
            URL[] classpathURLs = new URL[]{new File(jarPath).toURI().toURL()};
            ClassLoader loader = new URLClassLoader(classpathURLs);
            Class helloClass = loader.loadClass("hello.SimpleService");           
            Method sayHello = helloClass.getMethod("SayHello");            
            int modifiers = sayHello.getModifiers();

            if (Modifier.isPublic(modifiers)) {
               sayHello.invoke(this, null);
            } else {
                throw new NoSuchMethodException();
            }

        } catch (Exception ex) {
            ex.printStackTrace();
       }        
}


}
.
.

above TestPanel class is also created using java reflection and then that panel will be added into a JFrame.

all the things are working properly except when I click the jButton1 I get following exception,

java.lang.IllegalArgumentException: object is not an instance of declaring class
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    .
    .
    .
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6504)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6269)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4860)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4686)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2713)
    at java.awt.Component.dispatchEvent(Component.java:4686)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
    at java.awt.EventQueue.access$000(EventQueue.java:101)
    at java.awt.EventQueue$3.run(EventQueue.java:666)
    at java.awt.EventQueue$3.run(EventQueue.java:664)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:680)
    at java.awt.EventQueue$4.run(EventQueue.java:678)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Harsha
  • 3,268
  • 18
  • 48
  • 72
  • 1
    Can you specify which exact line throws that exception? – m0skit0 Jul 02 '13 at 11:52
  • sayHello.invoke(this, null); line throws the excetion. – Harsha Jul 02 '13 at 11:53
  • refer here http://stackoverflow.com/questions/160970/how-do-i-invoke-a-java-method-when-given-the-method-name-as-a-string. `this` is not an instance of SimpleService in your invocation – Tala Jul 02 '13 at 11:54

5 Answers5

3
sayHello.invoke(this, null);

The first argument is supposed to be a SimpleService. Change it to:

sayHello.invoke(helloClass.newInstance(), null);

For clarity you may change your code like this:

sayHello.invoke(helloClass.newInstance(), (Object[]) null);

or this:

sayHello.invoke(helloClass.newInstance());

Otherwise it may be misinterpreted as:

sayHello.invoke(helloClass.newInstance(), (Object) null);

or this:

sayHello.invoke(helloClass.newInstance(), new Object[]{null});
johnchen902
  • 9,200
  • 1
  • 25
  • 63
1

The SayHello method takes no arguments, so when calling it reflectively, don't pass anything except the instance. Also, the first parameter should be an instance of SimpleService:

Replace this:

sayHello.invoke(this, null);

with this:

sayHello.invoke(helloClass.newInstance());
Bohemian
  • 365,064
  • 84
  • 522
  • 658
1

sure, "this" is of type TestPanel and not of type SimpleService

Try the following:

   Class helloClass = loader.loadClass("hello.SimpleService");           

   Object args1[] = new Object[] {};
   Constructor<SimpleService> constructor = helloClass.getConstructor(args1);
   Object simpleService = constructor.newInstance();       

   sayHello.invoke(simpleService, null);

or shorter

   Class helloClass = loader.loadClass("hello.SimpleService");                 
   sayHello.invoke(helloClass.newInstance(), null);
beagle
  • 117
  • 1
  • 11
0

Notice this line: sayHello.invoke(this, null);

when using Method.invoke you need to supply an instance of the Class of which the Method is an instance. So to call sayHello.invoke you need to supply an instance of SimpleService.

Secondly, since SayHello does not take any arguments, the call should be sayHello.invoke(myinstance). Notice no second argument.

John B
  • 30,460
  • 6
  • 67
  • 92
0

For

sayHello.invoke(this, null);

this (TestPanel) is not an instance of SimpleService. You need an instance of SimpleService or you can make the SayHello method static:

public static void SayHello()

and then probably pass null instead for correctness: ("If the underlying method is static, then the specified obj argument is ignored. It may be null.")

sayHello.invoke(null, null);
Bernhard Barker
  • 50,899
  • 13
  • 85
  • 122