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

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

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

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


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

现在,我的问题来了:我想获得一个由我的应用程序构建的MyInterfaceImpl实例,该实例运行在Equinox的“外部” Java代码内部。我朴素的解决方案是在公共Object start(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实例交换这些类的实例? ?谢谢!

最佳答案

啊,这很棘手。我建议重新配置您的应用程序,并对所有内容都使用插件,但这不能回答您的问题。

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

希望这可以帮助。

08-19 13:15