Eclipse RCP: динамически загружать классы, определенные в библиотеке, на которую ссылается другой плагин - PullRequest
2 голосов
/ 06 апреля 2011

У меня есть плагин A, который ссылается на сторонний JAR.Я пытаюсь динамически загружать классы из этого JAR из плагина B.

У меня есть что-то вроде этого из класса в плагине B:

myClass = getClass().getClassLoader().loadClass("com.foo.Bar");

Это нормально работает, еслиЯ пытаюсь загрузить классы, определенные в плагине A, но я получаю ClassNotFoundException при попытке загрузить классы в JAR, на который ссылается плагин A.

JAR находится на пути к классам идоступно, когда я не пытаюсь динамически загрузить через этот загрузчик классов.

Есть идеи?

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 03 октября 2015

Я думаю, что ключом к вашему решению является следующее, которое я прочитал в другом посте: Каждый плагин Eclipse поддерживает свой собственный загрузчик классов .

Так что я могу рассказать вам, что такое мой Eclipse (3.7)Плагин предназначен для динамической загрузки, я не уверен, что вы сможете «подогнать» его под свои нужды.По сути, мой плагин выполняет шифрование / дешифрование.В качестве нового усовершенствования я разрешаю пользователю загружать один или несколько файлов Jar через FileDialog, где каждый файл JAR загружается с использованием URLClassLoader.Я создаю свой "пользовательский" загрузчик классов со следующей строкой:

this.FQCNLoader = new URLClassLoader ( getFQCNUrls(), this.getClass ().getClassLoader () );

Ключ должен был передать ClassLoader плагина Eclipse в качестве второго аргумента ... Это означает, что ваш "пользовательский" загрузчик классов имеет CLASSPATH изПлагин Eclipse плюс любые URL-адреса, которые вы добавляете (метод getFQCNUrls () возвращает URL-адрес []).

Другим ключевым моментом было сохранение «пользовательского» загрузчика классов в представлении, которое, как я знаю, сохраняется в течение всей жизни плагина Eclipse.Представление находится над всем кодом, который должен ссылаться на динамические классы * .jar.

Итак, вам нужно будет что-то делать в том же духе.Ваш "пользовательский" загрузчик классов должен был бы жить в классе выше как pluginA, так и pluginB.Кроме того, я бы подумал, потому что каждый плагин имеет свой собственный загрузчик классов, вам на самом деле нужно будет создать «пользовательский» загрузчик классов, который выполняет что-то вроде следующего:

1.) Let pluginB load dynamic *.jar/classes.  Convert into URL[].
2.) Create "custom" loader, pass in pluginB URL[] PLUS pluginA classloader.

Вот метод addURL ()в моем классе View, который создает «пользовательский» загрузчик классов ... это немного уродливо, потому что я написал его спешно, и он перестраивает «пользовательский» загрузчик классов каждый раз, когда пользователь загружает * .jar, но он работает в Eclipseи без OSGi:

private int             URLCount = 0; 
private URL[]           FQCNUrls = new URL[10];
private ClassLoader     FQCNLoader = new URLClassLoader ( this.FQCNUrls );

...Lots of code...

public  void addURL ( URL theURL ) throws IOException {
    //CPTest  lclsTest = new CPTest();
    if ( getURLCount () == 0 ) { 
        getFQCNUrls()[getURLCount()] = theURL;
        setURLCount ( 1 );
    }
    else { 
        boolean lisThere = false;
        for (int i = 0; i < getURLCount(); i++) {
            if (getFQCNUrls()[i].toString().equalsIgnoreCase(theURL.toString())) {
                lisThere = true;
            }
        }
        if ( lisThere ) { 
            System.out.println ( "File URL [" + theURL.toString () + "] already on the CLASSPATH!" );
        }
        else { 
            getFQCNUrls()[getURLCount()] = theURL;
            setURLCount ( getURLCount ()+1 );
        }

    }

    // CLEAR : Null out the classloader...
    this.FQCNLoader = null;
    // BUILD/RE-BUILD : the classloader...
    this.FQCNLoader = new URLClassLoader ( getFQCNUrls(), this.getClass ().getClassLoader () );

    //try {
    //    System.out.println ( "---------------------------------------------------------------------------" );
    //    System.out.println ( "Current Working Directory.............[" + System.getProperty ( "user.dir" ) + "]" );
    //    System.out.println ( "---------------------------------------------------------------------------" );
    //    System.out.println ( "this.classes []! " );
    //    lclsTest.dumpClasses ( this.getClass ().getClassLoader () );
    //    System.out.println ( "---------------------------------------------------------------------------" );
    //
    //    System.out.println ( "---------------------------------------------------------------------------" );
    //    System.out.println ( "File URL [" + theURL.toString () + "] added! " );
    //    lclsTest.dumpClasses ( this.FQCNLoader );
    //    System.out.println ( "---------------------------------------------------------------------------" );

    //    System.out.println ( "---------------------------------------------------------------------------" );
    //    System.out.println ( "ClassLoader.getSystemClassLoader() " );
    //    lclsTest.dumpClasses ( ClassLoader.getSystemClassLoader() );
    //    System.out.println ( "---------------------------------------------------------------------------" );

    //    Class  cls = this.FQCNLoader.loadClass ( "com.lmig.RRFECF.pso.security.nonproduction.CM_RRFECF_development_securitykey" );
    //  Class  cls = Class.forName(theFQCN, false, theClsLoader);
    //    theObjectKey = ( Object )  theClsLoader.loadClass(theFQCN);


    //}
    //catch ( Exception e ) {
    //// TODO Auto-generated catch block
    //    e.printStackTrace();
    //}

    Class sysclass = URLClassLoader.class;
    try {
        Method method = sysclass.getDeclaredMethod("addURL", parameters);
        method.setAccessible(true);
        method.invoke(getFQCNLoader(), new Object[] {
            theURL
        });
    }
    catch (Throwable t) {
        t.printStackTrace();
        throw new IOException(
            "Error, could not add URL to system classloader");
    }
}

Кстати, я рекомендую вам прочитать, что класс CPTest закомментирован в первой строке, для меня было неоценимо получить представление о различных загрузчиках классов и о том, чтобыл в них.Я оставил строки Sysout в коде, чтобы вы могли видеть, как выгрузить все классы в загрузчик классов ...

1 голос
/ 06 апреля 2011

Вы ошиблись в настройках.В идеале сторонний jar должен быть создан как плагин (File-> New-> Plugin из существующих jar-файлов), предоставляющий доступ к классам в jar-файле.Затем установите оба A & B в зависимости от него.

0 голосов
/ 06 апреля 2011

В плагине A убедитесь, что вы добавили jar для связывания пути к классам манифеста, а затем убедитесь, что экспортировали пакеты, содержащиеся в этом jar.

Открыть файл META-INF / MANIFEST-MF. Вы должны увидеть многостраничный редактор. Перейдите на вкладку Runtime и посмотрите раздел Classpath. Затем см. Раздел «Экспортированные пакеты». Затем перейдите на страницу Build и убедитесь, что ваш jar отмечен в разделе Binary Build.

...