使用反射调用pumpEvents时的java.lang.illegalArgumentException

时间:2011-11-07 10:28:59

标签: java swing reflection

我正在尝试在Java Applet中创建模态框架,如下所示:http://www.java2s.com/Tutorial/Java/0240__Swing/Showthegivenframeasmodaltothespecifiedowner.htm。此代码具有start()函数,看起来像

public void start() throws Exception {
  Class<?> clazz = Class.forName("java.awt.Conditional");
  Object conditional = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz },
      this);
  Method pumpMethod = Class.forName("java.awt.EventDispatchThread").getDeclaredMethod(
      "pumpEvents", new Class[] { clazz });
  pumpMethod.setAccessible(true);
  pumpMethod.invoke(Thread.currentThread(), new Object[] { conditional });
}.

当我打电话

 pumpMethod.invoke(Thread.currentThread(), new Object[] { conditional });

我有以下例外:

    java.lang.RuntimeException: java.lang.IllegalArgumentException: object is not an instance of declaring class
    at wizard.ModalFrameUtil.showAsModal(ModalFrameUtil.java:136)
    at wizard.WizardCore.showWizardFrame(WizardCore.java:206)
    at SelfRegistrationApplet$1.run(SelfRegistrationApplet.java:55)
    at SelfRegistrationApplet$1.run(SelfRegistrationApplet.java:35)
    at java.security.AccessController.doPrivileged(Native Method)
    at SelfRegistrationApplet.RunSelfRegistrationApplet(SelfRegistrationApplet.java:32)
    at SelfRegistrationApplet.init(SelfRegistrationApplet.java:26)
    at sun.applet.AppletPanel.run(AppletPanel.java:424)
    at java.lang.Thread.run(Thread.java:662)
Caused by: 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:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at wizard.ModalFrameUtil$EventPump.start(ModalFrameUtil.java:80)
    at wizard.ModalFrameUtil.showAsModal(ModalFrameUtil.java:133)
    ... 8 more

请告诉我这个调用有什么问题以及如何避免这种异常?

2 个答案:

答案 0 :(得分:1)

它的含义是Thread返回的Thread.currentThread()对象不是EventDispatchThread的实例。

避免问题的方法是找出该对象的类实际是什么,并使用那个类来获取Method对象。 (您应该能够通过在您尝试调用方法的地方打印从Thread.currentThread().getClass()获得的对象来找出它是什么。


invoke的Javadoc说明了这一点:

  

“抛出IllegalArgumentException - 如果方法是一个实例方法,并且指定的对象参数不是声明底层方法(或其子类或实现者)的类或接口的实例;如果是实际和形式参数不同;如果原始参数的展开转换失败;或者,如果在可能解包后,参数值无法通过方法调用转换转换为相应的形式参数类型。“

我对你的代码的阅读是你有正确的数字和类型的实际参数,所以它必须是线程类的问题。

答案 1 :(得分:0)

AWT和swing GUI是单线程的,事件调度线程是一个特殊的线程,应该运行所有的GUI操作。可能没有在GUI线程上调用您的方法。确保在事件调度线程上调用您的方法,您可以通过调用它来执行此操作

SwingUtilities.invokeAndWait(new Runnable(){public void run(){mymethod();}})

注意:javadocs不包含java.awt.EventDispatchThread,因此您可能依赖于某些实现细节。您可以使用java.awt.EventQueueToolkit.getSystemEventQueue()的子类代替。