Javassist使用OSGI在CtMethod.make和getDeclaredMethod中抛出notfound / null指针

时间:2017-03-29 11:43:24

标签: java reflection osgi javassist

javassist在CtMethod.make中抛出空指针com.company.test是Activator和Joe的包

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

}

}

当我使用pool实现池= new ClassPool(true); 它在getDeclaredMethod中抛出java.lang.NoClassDefFoundError:com / company / test / Joe

2 个答案:

答案 0 :(得分:0)

Class.forName(&#34; com.company.test.Joe&#34;)将使用从中调用的对象的ClassLoader。因此,在这种情况下,它将使用Activator类的ClassLoader。在OSGi中,类的ClassLoader通常是Class所在的bundle的ClassLoder。

bundle的ClassLoader只能加载bundle中的类和包含它的Import-Package语句的包中的类。

因此,如果要从任何包中加载Class,则不能简单地使用Class.forName。事实上,一个简单的类名在OSGi中甚至不是唯一的,因为不同的bundle可能会提供不同版本的包。

我不确定您的确切用例是什么。你使用一个固定的字符串作为名称,但我想你想加载一个名称来自某些来源的类,如配置。如果你给我更多关于用例的信息,那么我可以推荐如何处理这个问题。

答案 1 :(得分: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>