如何在 osgi 中从字节反序列化对象

2023-11-25

在我的 osgi 应用程序中,我有三个包,travel.api, table.api and utils. travel.api依赖于取决于table.api这取决于utils。注意travel.api不直接依赖于utils。我使用 aQute Bnd 生成清单,我相信它工作正常。清单如下所示。

有一个类叫做PageData有一个类型字段TableData,它又具有一个类型字段TestObject. PageData位于travel.api, TableData位于table.api and TestObject位于utils。当捆绑包加载时,这一切都可以正常工作。当我收到代表一个字节的数组时,问题就出现了PageData目的。我必须将其反序列化travel.api捆。这不应该是一个问题,因为它是在那里定义的。我用org.jboss.netty.handler.codec.serialization.ObjectDecoderInputStream并从类加载器中传递travel.api捆。下面显示的异常被抛出,但基本上它说:

Caused by: java.lang.ClassNotFoundException: com.openaf.utils.TestObject not 
    found by travel.api [9].

现在这是有道理的,因为如果你看看Import-Package for travel.api你会看到com.openaf.utils (where TestObject位于)未列出。如果我添加这个包,那么它会被正确反序列化。然而,这似乎不是一个好的通用解决方案,因为我必须遍历每个领域PageData使用并确保它们全部导入到该模块中,并递归地导入这些字段等包含的每个字段。

我在这里做错了什么吗?

使用 OSGi 时反序列化对象的最佳方法是什么?

如果我做得正确并且必须指定所有“深度”导入,有没有办法让 Bnd 进行“深度”生成?

任何帮助将不胜感激!

我使用 felix v4 作为我的 osgi 库。

Manifest-Version: 1
Bnd-LastModified: 1355404320862
Bundle-ManifestVersion: 2
Bundle-Name: travel.api
Bundle-SymbolicName: travel.api
Bundle-Version: 0
Created-By: 1.7.0_07 (Oracle Corporation)
Export-Package: com.openaf.travel.api;uses:="scala.runtime,scala,scala.c
 ollection,com.openaf.pagemanager.api,scala.reflect,com.openaf.table.api
 ";version="0.0.0"
Import-Package: com.openaf.pagemanager.api,com.openaf.table.api,scala,sc
 ala.collection,scala.reflect,scala.runtime
Tool: Bnd-1.44.0

Manifest-Version: 1
Bnd-LastModified: 1355404158858
Bundle-ManifestVersion: 2
Bundle-Name: table.api
Bundle-SymbolicName: table.api
Bundle-Version: 0
Created-By: 1.7.0_07 (Oracle Corporation)
Export-Package: com.openaf.table.api;uses:="scala.runtime,scala,scala.co
 llection,scala.reflect,scala.collection.immutable,scala.collection.gene
 ric,com.openaf.utils";version="0.0.0"
Import-Package: com.openaf.utils,scala,scala.collection,scala.collection
 .generic,scala.collection.immutable,scala.reflect,scala.runtime
Tool: Bnd-1.44.0

Manifest-Version: 1
Bnd-LastModified: 1355404158801
Bundle-ManifestVersion: 2
Bundle-Name: utils
Bundle-SymbolicName: utils
Bundle-Version: 0
Created-By: 1.7.0_07 (Oracle Corporation)
Export-Package: com.openaf.utils;uses:="scala.runtime,scala,scala.collec
 tion,scala.reflect";version="0.0.0"
Import-Package: scala,scala.collection,scala.reflect,scala.runtime
Tool: Bnd-1.44.0

java.io.InvalidClassException: failed to read class descriptor
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1585)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at org.jboss.netty.handler.codec.serialization.ObjectDecoderInputStream.readObject(ObjectDecoderInputStream.java:115)
at com.openaf.rmi.common.DefaultObjectEncoder$.decode(RMICommon.scala:33)
at com.openaf.rmi.client.ClientHandler.messageReceived(ClientPipelineFactory.scala:43)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296)
at org.jboss.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:363)
at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:345)
at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:211)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:94)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.processSelectedKeys(AbstractNioWorker.java:372)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:246)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:38)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.ClassNotFoundException: com.openaf.utils.TestObject not found by travel.api [9]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1460)
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:72)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1843)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at org.jboss.netty.handler.codec.serialization.ClassLoaderClassResolver.resolve(ClassLoaderClassResolver.java:30)
at org.jboss.netty.handler.codec.serialization.CachingClassResolver.resolve(CachingClassResolver.java:39)
at org.jboss.netty.handler.codec.serialization.CompactObjectInputStream.readClassDescriptor(CompactObjectInputStream.java:55)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1583)
... 28 more

谢谢,尼克。


这实际上听起来像是反序列化的一个严重缺陷?一个好的反序列化器应该使用导致加载的类的类加载器。给定的类加载器只能用于顶级对象,因为还没有父对象。

因此在这种情况下,给定的类加载器用于加载 PageData。 PageData的加载器用于加载TableData,而TableData的加载器必须用于加载TestObject。除非您使用的反序列化器确实大脑受损,否则没有任何逻辑原因会导致失败,因为这是虚拟机用来加载类的模型。我很惊讶 Java 反序列化器会这样做,我认为这种行为是一个严重的错误,因为它使用与 VM 不同的规则。

序列化是 OSGi 中的一个问题,因为模块化就是隐藏实现类;反序列化倾向于访问这些私有类,这是模块化的对立面。然而,对此有非常好的解决方案(其中不包括 Dynamic-ImportPackage,它以比仅使用普通 Java 更复杂和更昂贵的方式恢复到 JAR 地狱)。基本技巧是从公共 API 获得一个根对象,该对象可以访问私有/暂时需要的类。嗯,这听起来不像是一项服务吗?

Solution

看看人们对此有多么消极,看一个小例子,说明如何使用 Java 序列化(即 ObjectInputStream 和 ObjectOutputStream)解决问题。在您的问题中,您提到了 ObjectDecoderInputStream,这是一个我不熟悉的类。

设置是:

Bundle A:    class a.A { B b; }   (import b)
Bundle B:    class b.B { C c; }   (import c)
Bundle C:    class c.C { }

因此,让我们首先序列化一个对象:

ByteArrayOutputStream bous = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bous);

oos.writeObject(this);
oos.close();

现在是困难的部分。我们重写resolveObject方法,这让我们有机会实际进行正确的类加载......

ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bous.toByteArray())) {
    Set<ClassLoader>    lhs = new LinkedHashSet<ClassLoader>();
    {
        // Keep a set if discovered class loaders
        lhs.add(getClass().getClassLoader());
    }

    @Override
    protected Class< ? > resolveClass(ObjectStreamClass desc) 
         throws ClassNotFoundException, IOException {

         for (ClassLoader cl : lhs) try {
             Class< ? > c = cl.loadClass(name);

             // we found the class, so we can use its class loader,
             // it is in the proper class space  if the uses constraints 
             // are set properly (and you're using bnd so you should be ok)

             lhs.add(c.getClassLoader());

             // The paranoid among us would check
             // the serial uuid here ...
             // long uuid = desc.getSerialVersionUID();
             // Field field = c.getField("serialVersionUID");
             // assert uuid == field.get(null)

             return c;
         } catch (Exception e) {
           // Ignore
         }

         // Fallback (for void and primitives)
         return super.resolveClass(desc);
     }
 };

 // And now we've successfully read the object ...

 A clone = (A) in.readObject();

请注意,只有在正确导出瞬态图的情况下,这才有效。 IE。如果你能做到new TableData那么这也应该有效。一个不起作用的例子是,如果您从接口获取实现。接口类未连接到 impl。班级。 IE。如果您有一个扩展 TableData 的 TableDataImpl,那么您就完蛋了。在这些情况下,您需要一些服务来查找实现的“域”。

祝你好运。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 osgi 中从字节反序列化对象 的相关文章

随机推荐

  • python球物理模拟

    我看过 Peter Colling Ridge 的精彩教程 http www petercollingridge co uk pygame physical simulation 我正在扩展 PyParticles 脚本该代码可以在网站上获
  • 任务“:app:kaptGenerateStubsDebugKotlin”执行失败

    将 android studio 从 electricEel 更新为 Flamingo 插件后id kotlin kapt 导致错误 Execution failed for task app kaptGenerateStubsDebugK
  • 分配在堆上的对象

    每当创建任何新对象时 都会在堆上创建该对象 为每个对象分配的内存有两个附加字段 1 类型对象指针 2 同步块索引 这两个字段到底有什么用途 有人能解释一下吗 类型对象指针用于表示对象的类型 这是必需的 方法查找 vtable 检查石膏 寻找
  • HTML Purifier - 净化什么?

    我正在使用 HTML Purifier 来保护我的应用程序免受 XSS 攻击 目前 我正在净化所见即所得编辑器中的内容 因为这是唯一允许用户使用 XHTML 标记的地方 我的问题是 我是否应该在登录身份验证系统中的用户名和密码 或注册页面的
  • 在自定义编辑类型字段中添加多个输入元素

    有没有办法创建具有多个输入元素的自定义字段 我正在咨询文档创建单个输入元素非常简单 但我不太确定如何添加多个输入元素 以前有人走过这座桥吗 如果是这样 你是怎么做到的 这是一些示例代码 name Dimensions index Dimen
  • 在 BrowseFragment 中禁用行缩放/展开

    我还没有找到任何文档如何在将焦点从标题切换到 BrowseFragment 中的片段时禁用行缩放 倚背版本 24 2 0 BrowseFragment有一个功能enableMainFragmentScaling这部分解决了问题 图像现在具有
  • 如何查看是否点击同一个元素两次? jQuery

    如何检测用户是否点击同一个 div 我尝试过这个但没有成功 oldthis null var this this if oldthis this alert You clicked this last oldthis this 您无法比较
  • Laravel Auth::logout 未删除记住我的 cookie

    因此 我将会话的生命周期设置为两周 这样用户就不必多次登录或退出 然而今天我注意到一些事情 如果您注销 它会破坏您的会话 但会在您的浏览器上保留 记住我 cookie 这会导致问题 因为如果您在同一台计算机上切换帐户 8 10 次 您会收到
  • 事务中的 LAST_INSERT_ID() 可靠吗?

    我正在使用 mysql ado net C 这是我的问题 我知道 mysql 是并发的 但是我有文件数据 缩略图名称 和数据库数据 行 同步 如果我开始一笔交易 但因任何原因失败 这会是一个问题吗 如果我在两个核心上同时运行这段代码 它们会
  • 在iPhone App中如何检测设备的屏幕分辨率

    在 iPhone 应用程序中 在设备上运行App时如何检测运行App的设备的屏幕分辨率 CGRect screenBounds UIScreen mainScreen bounds 这将为您提供整个屏幕的分辨率 以点为单位 因此 iPhon
  • 异常处理模式

    这是我看到的一种常见模式 其中与异常相关的错误代码存储为静态最终整数 当创建要抛出的异常时 它是用这些代码之一以及错误消息构造的 这导致要捕获它的方法必须查看代码 然后决定操作过程 另一种选择似乎是为每个异常错误情况声明一个类 尽管相关异常
  • 在 Swing 应用程序中组织操作?

    我当前的应用程序有一个 JFrame 其中约有 15 个操作存储为 JFrame 中的字段 每个操作都是一个匿名类 其中一些非常长 将操作分解为它们自己的类 可能位于称为操作的子包中 是否很常见 如果不是 通常如何控制这种复杂性 Thank
  • 如何使用 mysql 二进制日志从删除数据库命令恢复?

    如何恢复使用 drop database 命令删除的 mysql 数据库 我可以访问二进制日志 这应该使这种类型的回滚成为可能 文档很糟糕 它暗示 DROP DATABASE 是可恢复的 但仅在我不熟悉的奇怪条件下http dev mysq
  • Flutter - 无线电动画未显示在 showDialog 上

    我正在尝试创建一个Radio in a showDialog 但是发生的动画Radio没有出现在showDialog 例如 当点击时foo2什么也没有发生 当你退出时showDialog然后回到它 foo2被选中 下面是代码和 gif 显示
  • C# 委托中的元帅 va_list

    我正在尝试用 c 来完成这项工作 C 标头 typedef void LogFunc const char format va list args bool Init uint32 version LogFunc log C 实现 stat
  • Java 同步和性能的一个方面

    我刚刚意识到我需要在某个方面同步大量数据收集代码 但性能是一个真正值得关注的问题 如果性能下降太多 我的工具就会被淘汰 我将分别写入 int 和 long 以及各种数组 ArrayList 和 Map 应用程序将有多个线程进行函数调用 这些
  • 如何使用 SASS 进行媒体查询?

    我已经通读了 SASS 文档 只能找到如何使用 scss 语法而不是 sass 语法进行媒体查询 sass 是具有严格的空白 没有大括号或分号的语法 如何使用 sass 语法进行媒体查询 media screen and min heigh
  • pcl::RANSAC 分割,获取云中的所有平面?

    我有一个点云库函数 可以检测点云中最大的平面 这很好用 现在 我想扩展此功能以分割云中的每个平面并将这些点复制到新的云中 例如 房间地板上有球体的场景将返回地板和墙壁 但不是球体 因为它不是平面的 如何扩展下面的代码以获得所有飞机 而不仅仅
  • 内部版本号中的分支名称

    我试图将分支名称放入内部版本号中 但找不到正确的参数 我正在使用内部版本号格式 teamcity build branch 0 它可以工作 但是当它尝试构建默认分支 dev 时 teamcity 将其命名为
  • 如何在 osgi 中从字节反序列化对象

    在我的 osgi 应用程序中 我有三个包 travel api table api and utils travel api依赖于取决于table api这取决于utils 注意travel api不直接依赖于utils 我使用 aQute