Создать объект класса, содержащий анонимный внутренний класс, с помощью отражения - PullRequest
2 голосов
/ 23 ноября 2011

Я пытаюсь создать объект класса Test , содержащий анонимный внутренний класс - 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();
    }
}

Ответы [ 2 ]

2 голосов
/ 24 ноября 2011

Пойдем еще раз ...

Так что это IllegalAccessError, не путать с IllegalAccessException (расширяет ReflectiveOperationException в Java SE 7). Речь идет о том, чтобы испортить классы, а не размышлять.

Выглядит так, как будто вы загрузили один из классов с помощью «пользовательского» загрузчика классов, а другой - с помощью обычного загрузчика классов. Даже если имена пакетов совпадают, классы, загруженные из разных загрузчиков классов, находятся в разных пакетах (из раннего обновления J2SE 1.2, IIRC). Один класс пытается получить доступ (связать) с другим, полагаясь на «частный доступ к пакету», но JVM отказывает в этом, потому что пакеты на самом деле отличаются.

0 голосов
/ 24 ноября 2011

Вы писали:

    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();
    }
}

Этот код не будет работать надежно; Внимательное чтение JavaDoc файлов FileInputStream.available и FileInputStream.read должно раскрыть причину.

Возможно, что искалеченные данные файла класса вносят вклад в это исключение.

...