您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

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

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

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

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

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

看看人们对此有何看法,这是一个小示例,说明如何使用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();

请注意,这仅在正确导出瞬态图的情况下才有效。即,如果您可以这样做,new TableData那么这也应该起作用。一个不起作用的示例是,例如,如果您从接口获取实现。接口类未连接到impl。类。即,如果您具有扩展了TableData的TableDataImpl,那么您将被搞砸。在这些情况下,您需要一些服务来找到实现的“域”。

祝好运。

其他 2022/1/1 18:32:43 有495人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶