Java OSGi容器中的RMI客户端

Java OSGi容器中的RMI客户端,java,osgi,rmi,Java,Osgi,Rmi,我需要在OSGi包中公开一个基于RMI的系统。RMI客户机“bundle”是一个jar,我使用bnd工具将其转换为OSGi包(我没有访问源代码的权限),至少在eclipse中一切似乎都很好,但是当我尝试连接到RMI服务器时,抛出了一个ClassCastException,很可能是因为OSGi和RMI都很有趣地使用了类加载器 我怎样才能解决这个问题?也许将RMI客户机jar用作“系统”包 以下是堆栈跟踪: Blipnet OSGi service starting... com.blipsyste

我需要在OSGi包中公开一个基于RMI的系统。RMI客户机“bundle”是一个jar,我使用bnd工具将其转换为OSGi包(我没有访问源代码的权限),至少在eclipse中一切似乎都很好,但是当我尝试连接到RMI服务器时,抛出了一个ClassCastException,很可能是因为OSGi和RMI都很有趣地使用了类加载器

我怎样才能解决这个问题?也许将RMI客户机jar用作“系统”包

以下是堆栈跟踪:

Blipnet OSGi service starting... com.blipsystems.blipnet.api.blipserver.BlipServerConnectionException: There was a problem connecting to the server at com.blipsystems.blipnet.api.core.blipserver.BlipServerConnectionAdapter.(Unknown Source) at com.blipsystems.blipnet.api.core.blipserver.BlipServerConnectionAdapter.(Unknown Source) at com.blipsystems.blipnet.api.blipserver.BlipServer.getConnection(Unknown Source) at dk.itu.jingling.blipnetosgi.BlipnetConnectionService.setup(BlipnetConnectionService.java:28) at dk.itu.jingling.blipnetosgi.BlipnetConnectionService.(BlipnetConnectionService.java:22) at dk.itu.jingling.blipnetosgi.Activator.start(Activator.java:32) at org.apache.felix.framework.util.SecureAction$Actions.run(SecureAction.java:1235) at java.security.AccessController.doPrivileged(Native Method) at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:658) at org.apache.felix.framework.Felix.activateBundle(Felix.java:1699) at org.apache.felix.framework.Felix.startBundle(Felix.java:1621) at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:890) at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:877) at org.apache.felix.fileinstall.internal.DirectoryWatcher.start(DirectoryWatcher.java:819) at org.apache.felix.fileinstall.internal.DirectoryWatcher.start(DirectoryWatcher.java:805) at org.apache.felix.fileinstall.internal.DirectoryWatcher.startAllBundles(DirectoryWatcher.java:798) at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:299) Caused by: java.lang.ClassCastException: com.blipsystems.blipnet.blipserver.cms.NewApiHandler_Stub cannot be cast to com.blipsystems.blipnet.api.core.blipserver.RemoteBlipServerConnection Blipnet OSGi服务正在启动。。。 com.blipsystems.blipnet.api.blipserver.blipserver连接异常:连接到服务器时出现问题 位于com.blipsystems.blipnet.api.core.blipserver.BlipServerConnectionAdapter。(来源未知) 位于com.blipsystems.blipnet.api.core.blipserver.BlipServerConnectionAdapter。(来源未知) 位于com.blipsystems.blipnet.api.blipserver.blipserver.getConnection(未知源) 在dk.itu.kingling.blipnetosgi.BlipnetConnectionService.setup(BlipnetConnectionService.java:28) 在dk.itu.kingling.blipnetosgi.BlipnetConnectionService.(BlipnetConnectionService.java:22) 在dk.itu.kingling.blipnetosgi.Activator.start(Activator.java:32) 位于org.apache.felix.framework.util.SecureAction$Actions.run(SecureAction.java:1235) 位于java.security.AccessController.doPrivileged(本机方法) 位于org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:658) 位于org.apache.felix.framework.felix.activateBundle(felix.java:1699) 位于org.apache.felix.framework.felix.startBundle(felix.java:1621) 位于org.apache.felix.framework.BundleImpl.start(BundleImpl.java:890) 位于org.apache.felix.framework.BundleImpl.start(BundleImpl.java:877) 位于org.apache.felix.fileinstall.internal.DirectoryWatcher.start(DirectoryWatcher.java:819) 位于org.apache.felix.fileinstall.internal.DirectoryWatcher.start(DirectoryWatcher.java:805) 位于org.apache.felix.fileinstall.internal.DirectoryWatcher.startAllBundles(DirectoryWatcher.java:798) 位于org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:299) 原因:java.lang.ClassCastException:com.blipsystems.blipnet.blipserver.cms.NewApiHandler_存根无法强制转换为com.blipsystems.blipnet.api.core.blipserver.remoteblipserver连接
由于类可见性问题,标准Java序列化和OSGi不能很好地混合,并且由于RMI构建在序列化之上

如果你四处搜索,你会发现很多人询问RMI和OSGi,但很少有人询问具体的解决方案

我还没有坐下来研究RMI和OSGi的具体问题,但我确实解决了使用Spring的
HTTPInvoker
的问题,它仍然使用Java的序列化机制

问题归结为一个类:
ObjectInputStream

这是负责反序列化的人——要反序列化一个对象,您需要了解它的类。如果您有一个现代的IDE,您可以查看这个类的继承层次结构,并看到它有许多扩展,包括一些特定于RMI的类

我的解决方案是使用Spring的可扩展实现
ObjectInputStream
,并从我的包中插入类加载器,这样反序列化就可以访问可以查看我的类的类加载器

您可以随意使用系统捆绑包,但这确实是一种攻击,我不建议长期使用

不幸的是,OSGi仍然有一些令人讨厌的地方,需要您深入到抽象的层次来发现问题并解决它——RMI就是其中之一


这些家伙声称在他们的RMI服务结构服务器产品(基于OSGi的服务器)中有一个解决方案,可以配置为与Felix一起工作(我认为Eclipse的Equinox是默认的)。

我也遇到了同样的问题,我很惊讶它是多么容易解决。我有三包:bundleA、bundleB、bundleC。bundleA—一组对bundleB和bundleC一无所知的抽象类。BundleB使用bundleA和bundleC。bundleB使用bundleC

所以,
bundleA bundleC

在bundleA中,我有调用RMI服务器并使用bundleC中的类的代码。这里我遇到了一个问题——ClassNotFoundException。下面是我在bundleA类中使用的代码

ClassLoader threadClassLoader= Thread.currentThread().getContextClassLoader();
try {
    Class bundleCSomeClass = someVariablePassedFromBundleB.getMyClass();
    Thread.currentThread().setContextClassLoader(bundleCSomeClass.getClassLoader());
    //here we are calling RMI service
} catch (RemoteException ex) {

}finally{
    Thread.currentThread().setContextClassLoader(threadClassLoader);
}

我可以帮助发布异常,特别是哪个类受到影响。ClassCastException,NoClassDefFoundErrors,。。。在春分点(个人经验;)内很常见。史蒂夫,谢谢你的回复,反正我不太明白:通过“使用Spring的HttpInvoker”,你是说你使用HttpInvoker作为RMI服务的客户端?因为RMI库是一个封闭源代码的专有库,它们提供服务器和客户端,但我没有办法更改它们。除此之外,他们在类中广泛使用回调,这意味着RMI客户机也变成了RMI服务器,因此我不知道HttpInvoker在这些情况下是否会有所帮助HttpInvoker只是解决相关问题(序列化)的比较-我不是建议你使用它。你需要用低级RMI来解决问题-你有权在库中调试源代码吗?像往常一样,没有:)事实上,我试图在OSGi容器中共享库(我知道,这不是一件好事),但我没有管理()