2011-04-05 8 views
2

サードパーティのJARを参照するプラグインAがあります。私がしようとしている場合、これは正常に動作しますEclipse RCP:別のプラグインで参照されるライブラリで定義されたクラスを動的にロードする

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

:私は、私は、プラグインB内のクラスから、このような何かを持っている動的プラグインB.

からこのJARからクラスをロードしようとしていますプラグインAで定義されているクラスをロードするには、プラグインAで参照されるJARでクラスをロードしようとするとClassNotFoundExceptionが発生します。

JARはクラスパス上にあり、このクラスローダ経由で動的にロードしようとしません。

アイデア?

ありがとうございます。

答えて

1

設定が間違っています。理想的には、サードパーティのjarをプラグインとして作成する必要があります(ファイル - >新規 - >既存のjarからのプラグイン)。jarのクラスを公開します。次に、A & Bの両方を設定します。

+0

あなたはおそらく正しいですが、これは私たちのアプリケーションで実行可能なオプションではありません。私の問題では、リフレクションを使用してクラスを動的にインスタンス化し、代わりにコード生成を行うことに反対しました。 – lucks

0

プラグインAでは、マニフェストクラスパスをバンドルするためにjarを追加したことを確認してから、そのjarファイルに含まれているパッケージを必ずエクスポートしてください。

META-INF/MANIFEST-MFファイルを開きます。複数ページのエディタが表示されます。ランタイムタブに移動し、クラスパスセクションを参照してください。次に、「エクスポートされたパッケージ」セクションを参照してください。次に、[ビルド]ページに移動して、バイナリビルドセクションでjarがオンになっていることを確認します。

+0

うん、それはすべてそこにある。設定は通常の状況下で動作します...実行時にバンドルクラスローダーを使用してクラスを動的にロードするときに問題が発生します – lucks

+0

@lucks:あなたと他の人: - /サードパーティのJDBCドライバを直接使用してみました。 Eclipseフレームワーク?私はこれを行うために雇用しなければならなかった様々なハッキングを考えると、私はまだ震えます... – thkala

+0

バンドルクラスローダーが動作していない場合、正しい設定の1つが得られませんでした。私が参照したセクションをすべてダブルチェックしてください。 –

1

あなたの解決策の鍵は、私が別の投稿で読んだのは、です。各Eclipse Pluginは、独自のクラスローダーを維持しています。

私はEclipse(3.7)プラグインが動的ロードのために何をしているのかを知ることができます。あなたのニーズに「フィット」できるかどうかはわかりません。基本的に、私のプラグインは暗号化/復号化を行います。新しい拡張として、ユーザーはFileDialog経由で1つ以上のJarファイルをロードできます。ここで、各jarファイルはURLClassLoaderを使用してロードされます。

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

キーが2番目の引数として、Eclipseのプラグインのクラスローダに渡すことだった...これはあなたの「カスタム」クラスローダは、EclipseプラグインのCLASSPATHを有することを意味:私は次の行で私の「カスタム」クラスローダの作成しますあなたが追加しているURLを加えます(getter 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()メソッドは次のとおりです。また、私はそれぞれのプラグインは、それが自分のクラスローダのしているので、あなたが実際には次のような何かを「カスタム」クラスローダを構築するために必要になるだろうと思うだろう"カスタム"クラスローダーを構築するビュークラス...私は急いでそれを書いて、ユーザーが*をロードするたびに "カスタム"クラスローダーを再構築するので、少し醜いです。瓶が、それは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行を残しました。