2011-11-23 188 views
2

创建一个包含匿名内部类的类的对象,我想创建一流测试包含匿名内部类的对象 - 的ActionListener - 通过反射。通过反射

该类正确加载。我可以列出任何字段,方法,构造函数等。问题是,当我试图创建包含一些按钮的包含ActionListeners的构造函数的对象时。当听众被注释掉时,一切正常。

当我使用Constructor.newInstance()方法,我发现了:

java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) 
    at java.lang.reflect.Constructor.newInstance(Unknown Source) 
    at Engine.createObj(Engine.java:78) 
    at Main$3.actionPerformed(Main.java:107) 
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) 
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) 
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) 
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source) 
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) 
    at java.awt.Component.processMouseEvent(Unknown Source) 
    at javax.swing.JComponent.processMouseEvent(Unknown Source) 
    at java.awt.Component.processEvent(Unknown Source) 
    at java.awt.Container.processEvent(Unknown Source) 
    at java.awt.Component.dispatchEventImpl(Unknown Source) 
    at java.awt.Container.dispatchEventImpl(Unknown Source) 
    at java.awt.Component.dispatchEvent(Unknown Source) 
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) 
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) 
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) 
    at java.awt.Container.dispatchEventImpl(Unknown Source) 
    at java.awt.Window.dispatchEventImpl(Unknown Source) 
    at java.awt.Component.dispatchEvent(Unknown Source) 
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source) 
    at java.awt.EventQueue.access$000(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.awt.EventQueue$3.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue$4.run(Unknown Source) 
    at java.awt.EventQueue$4.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) 
    at java.awt.EventQueue.dispatchEvent(Unknown Source) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source) 
    at java.awt.EventDispatchThread.run(Unknown Source) 
Caused by: java.lang.IllegalAccessError: tried to access class Test.Test$2 from class Test.Test 
    at Test.Test.<init>(Test.java:123) 
    ... 42 more 

Test.java:123是其中听者实现当然。 Test.Test $ 2是匿名内部类文件。

加载类的代码看起来像细的工作:

public void loadClass(File file) { 
    reflectClass = null; 
    try { 
     FileInputStream fis = null; 
     fis = new FileInputStream(file); 
     byte[] bytes = new byte[fis.available()]; 
     int read = fis.read(bytes); 
     fis.close(); 
     if (read != bytes.length) { 
      return; 
     } 
     reflectClass = defineClass(null, bytes, 0, bytes.length); 
     resolveClass(reflectClass); 
    } catch (Exception e1) { 
     e1.printStackTrace(); 
    } 
} 

和对象创建:

public void createObj(Constructor ct) { 
    Class[] types = ct.getParameterTypes(); 
    //... some params generating code, not important, i'm using non-param constructor. 
    try { 
     object = ct.newInstance(oParams); // Here is the problem. 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

回答

0

您写道:

public void loadClass(File file) { 
    reflectClass = null; 
    try { 
     FileInputStream fis = null; 
     fis = new FileInputStream(file); 
     byte[] bytes = new byte[fis.available()]; 
     int read = fis.read(bytes); 
     fis.close(); 
     if (read != bytes.length) { 
      return; 
     } 
     reflectClass = defineClass(null, bytes, 0, bytes.length); 
     resolveClass(reflectClass); 
    } catch (Exception e1) { 
     e1.printStackTrace(); 
    } 
} 

此代码将无法可靠地工作;仔细阅读FileInputStream.available和FileInputStream.read的JavaDoc应该会揭示原因。

这可能是残缺的类文件数据有助于该异常。

+0

实际上它可能适用于一定大小的文件,然后神秘地失败。将一个文件读入字节数组的API调用可能是一个好主意。 –

2

我们有另一个去......

所以这是一个IllegalAccessError,不要与IllegalAccessException混淆(在Java SE 7的延伸ReflectiveOperationException)。这是关于弄乱类,而不是反思。

看起来好像您已经使用“自定义”类加载器加载了其中一个类,而另一个则是通过普通类laoder加载的。即使包名称匹配,从不同类加载器加载的类也是在不同的包中(来自J2SE 1.2,IIRC的早期更新)。一个类尝试访问(链接)另一个依赖于“包专用”访问,但JVM拒绝它,因为包实际上是不同的。

+0

我调用的ClassLoader默认构造函数的文档说:“使用方法** getSystemClassLoader()**返回的ClassLoader创建一个新的类加载器作为父类加载器。”那么最终它不应该使用“普通”类加载器吗?无论如何,我试图使用系统类加载器,但无法找到任何方式从文件加载类。 –

+0

@dragoste系统类加载器将是父类,但它仍然是一个不同的类加载器。 –