我面临的一个问题是“普通” Java,Equinox和两者之间的通信的结合。我已经阅读了其他相关问题(here,here和there以及其他网站,例如this one和that 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中添加导入。
希望这可以帮助。