2017-03-29 14 views
2

JavassistのがCtMethod.makeのcom.company.testにNULLポインタを投げているOSGIを使用する活性化剤およびジョーJavassistのが

public class Activator implements BundleActivator { 

public Class<?> creerClasse() { 
    CtClass toGenerateClass; 
    ClassPool pool; 
    pool = ClassPool.getDefault(); 
    try { 
     Class c; 
     c = Class.forName("com.company.test.Joe"); 
     pool.appendClassPath(new ClassClassPath(c)); 
    } catch (ClassNotFoundException e1) { 
     e1.printStackTrace(); 
    } 

    pool.importPackage("com.company.test"); 

    toGenerateClass = pool.makeClass("Test118"); 

    try { 
     toGenerateClass 
       .addMethod(CtMethod 
         .make("public void afficher (com.company.test.Joe msg) { System.out.println(msg); } ;", 
           toGenerateClass)); 
    } catch (CannotCompileException e) { 
     e.printStackTrace(); 
    } 

    try { 
     return toGenerateClass.toClass(); 
    } catch (CannotCompileException e) { 
     e.printStackTrace(); 
     return null; 
    } 
} 


public void start(BundleContext context) throws Exception { 


     Class<?> genClass = creerClasse(); 
     Class<?> c = Class.forName("com.company.test.Joe"); 

     for (Method me : genClass.getDeclaredMethods()) { // test print, ok 
      System.out.println(me); 
     } 

     Method method = genClass.getDeclaredMethod("afficher", c); 

     Joe person = new Joe(); 
     person.setId(17); 
     method.invoke(genClass.newInstance(), person); 

} 

} 

iはinstansiateのパッケージでCtMethod.makeとgetDeclaredMethodでNOTFOUND /ヌルポインタをスロープール付きプール=新しいClassPool(true)。 は、それがスローます。java.lang.NoClassDefFoundError:COM /会社/テスト/ジョー・getDeclaredMethod

答えて

0

にClass.forName(「com.company.test.Joe」)それから呼び出されるオブジェクトのクラスローダを使用しますインチこの場合、ActivatorクラスのClassLoaderが使用されます。 OSGiでは、クラスのClassLoaderは、通常、クラスが入っているバンドルのClassLoderです。

バンドルのClassLoaderは、バンドル内にあるクラスとパッケージ内のクラスをインポートできます。 。

したがって、任意のパッケージからクラスをロードする場合は、単にClass.forNameを使用することはできません。実際、異なるバンドルがパッケージを異なるバージョンで提供する可能性があるので、単純なクラス名はOSGiでも一意ではありません。

正確なユースケースがわかりません。名前には固定ストリングを使用しますが、設定のようなソースから来る名前でクラスをロードしたいと思います。ユースケースに関する詳細情報を私に与えたら、この問題へのアプローチ方法をお勧めします。

+0

ありがとうございました。 私は実際に別のバンドルで別のクラスを使用しているクラス 'A'を実際に動的に生成したいとします。この場合は' com.company.test.Joe' このクラスは 'A'クラスのmethodeのパラメータになります'A'のインスタンスを作成してメソッドを呼び出します。 マニフェストに 'Import-Package'、' DynamicImport-Package'と他のバンドルの 'dependency'も追加しました。また、' com.company.test.Joe'を含むパッケージを他のバンドルからエクスポートしました –

0

私はこの問題を解決しました。 OSGi環境では、javassitプールを初期化して、インポートされたクラスを見つけ、NullPointerExceptionを投げないようにする必要があります。

pool = new ClassPool(true); 
    pool.insertClassPath(new LoaderClassPath(this.getClass() 
      .getClassLoader())); 

と生成されたクラスを使用して起動するため、このよう

toGenerateClass.toClass(this.getClass() 
       .getClassLoader(), getClass().getProtectionDomain()); 

で作成する必要があります方法は、他のバンドルから動的にエクスポートしたパッケージをロードするために<DynamicImport-Package>PACKAGENAME</DynamicImport-Package>を追加することを忘れないでくださいです。

PS:パッケージをエクスポートするには<Export-Package>PACKAGENAME</Export-Package>

関連する問題