从Equinox / Eclipse中获取对象

时间:2013-07-24 01:30:18

标签: java eclipse-plugin jvm classloader equinox

我面临的问题是“普通”Java,Equinox以及两者之间的通信。我已阅读其他相关问题(hereherethere以及其他网站,例如this onethat one),但找不到一个令人满意的(或工作!)解决方案。

我有一组插件:P1,P2和P3。 P1导出一些由P2使用的类。 P2还导出P3使用的其他类和接口。特别是,P2定义并导出接口MyInterface ,其实现类MyInterfaceImpl实现了MyInterface 。 P3是一个应用程序,因此包含类Launcher实现IApplication 并定义公共对象启动(IApplicationContext)方法。一切都很好。当我从Eclipse运行Launcher作为Eclipse应用程序时,它运行正常。启动器使用 MyInterface MyInterfaceImpl

现在,我使用以下(简单)代码以编程方式运行我的应用程序,根据各种帖子,这似乎是运行Equinox / Eclipse应用程序的“好”方式:

void callApplication() {
    final String[] args =
        new String[] {
            "-application",
            "Launcher",
            ... };
    EclipseStarter.run(args, null);
}

同样,这段代码工作正常,我可以“看到”我的应用程序运行并产生预期的结果。

现在,我的问题出现了:我想获得一个由我的应用程序构建的 MyInterfaceImpl 实例,在Equinox中运行,回到“外部”Java代码中。我天真的解决方案是在公共对象启动(IApplicationContext)方法中返回此对象,并按如下方式修改我的调用代码:

MyInterface callApplication() {
    final String[] args =
        new String[] {
            "-application",
            "Launcher",
            ... };
    return (MyInterface) EclipseStarter.run(args, null);
}

但这种天真的解决方案不起作用。我收到 java.lang.ClassCastException:MyInterfaceImpl无法强制转换为MyInterface 。考虑到它,它是有道理的,因为,在 callApplication()的末尾,我有两个“版本”的对{ MyInterface MyInterfaceImpl }:来自“外部”Java代码的一个,由JVM类加载器加载,另一个来自Equinox,由Equinox类加载器加载。我修改了我的代码以打印返回对象的类加载器和 MyInterface

final Object o = EclipseStarter.run(args, null);
System.out.println(o.getClass().getClassLoader());
System.out.println(MyInterface.class.getClassLoader());

而且,事实上,我获得了:

org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@7e66458c[P2:1.5.0(id=413)]
sun.misc.Launcher$AppClassLoader@1efc3d2

请注意,返回对象的类加载器据说来自P2,正如预期的那样,因为P2是定义和导出 MyInterface MyInterfaceImpl 。

我尝试了不同的方法来获得{ MyInterface MyInterfaceImpl }的“兼容”对,但到目前为止没有运气(我总是得到相同的 java。 lang.ClassCastException:MyInterfaceImpl无法强制转换为MyInterface ):

  • 我尝试设置属性-Dorg.osgi.framework.bootdelegation = * -Dorg.osgi.framework.system.packages.extra = MyInterface,MyInterfaceImpl。

  • 我还尝试拦截 start()方法中的 DefaultClassLoader

所以,我的问题是:是否有一种方法可以使用Java程序,该程序使用项目中定义的某些类(也是插件并导出这些类)来交换这些类的实例。 Eclipse的一个实例以编程方式启动?谢谢!

1 个答案:

答案 0 :(得分:1)

啊,这个很棘手。我建议重新架构你的应用程序并使用插件来处理所有问题,但这不能回答你的问题。

现在,您要做的是首先,删除P2的接口定义并将其添加到原始(非OSGi)JAR中,最好是在一个包中,比如说com.example.api。然后,添加-Dorg.osgi.framework.system.packages.extra=com.example.api;还为该包添加P2和P3中的导入。

希望这有帮助。