2010-08-13 66 views
2

我试图通过专用通信捆绑包将对象从捆绑包发送到其他框架。对于通信,我使用TCP/IP上的Java标准序列化(使用ObjectStreams)。在OSGi中自定义类型数组的反序列化

通信流程如下:发送程序包会将可序列化的对象传递给发送 - 发送方,后者将序列化对象并通过TCP/IP将它们发送到发送接收器。接收器将对接收到的对象进行反序列化,并将它们传递给接收器包。因为OSGi类加载体系结构不同于本机体系结构,所以我必须对类加载器做一点小事:因为我认为接收器包应该知道他接收到的类(=是否已导入或以其他方式访问它们通过类加载器),我使用接收器的类加载器而不是发送器来加载类。 (通过Bundle.loadClass(..)方法)。 这适用于自定义类,但是,这不适用于自定义类型的数组。 (其不知道的发射 - 接收机的类加载器,但向接收器束。)

编辑: ObjectInputStream.readObject(...)抛出ClassNotFoundException的,如果它试图反序列化阵列。 (我认为这个异常起源于接收包的Bundle.loadClass(...)方法。)

它可以与java.util.List或其他Serializable类一起工作。它也适用于包含其他自定义类型的字段的自定义类型,只要它们不是数组。

所以问题是:数组的de/serialized方式有什么不同吗?或者他们装载不同?

回答

3

我怀疑你已经使用Bundle.loadClass直接实现了ObjectInputStream.resolveClass。如果是这样,你遇到这个问题:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6516909

基本上,ClassLoader.loadClass从来没打算用于数组类。加载数组类的最简单方法是使用Class.forName。不幸的是,使用OSGi没有简单的方法。你要么需要一个Bundle的ClassLoader代理,或者你需要做的类名称一些预处理,以确保您不会直接传递数组的loadClass:

public static Class<?> bundleClassForName(Bundle bundle, String name) throws ClassNotFoundException { 
    int length = name.length(); 
    if (length > 0 && name.charAt(0) == '[') { 
     int pos = 1; 
     while (pos < length && name.charAt(pos) == '[') { 
      pos++; 
     } 

     if (pos < name.length()) { 
      if (name.charAt(pos) != 'L') { 
       return Class.forName(name); 
      } 

      if (name.charAt(length - 1) == ';') { 
       String componentName = name.substring(pos + 1, length - 1); 
       Class<?> klass = bundle.loadClass(componentName); 
       ClassLoader loader = klass.getClassLoader(); 
       return Class.forName(name, false, loader); 
      } 
     } 
    } 

    return bundle.loadClass(name); 
} 
+0

这是真的,我们在这里运行这个bug ....我们尝试过的一个肮脏的解决方法是使用动态导入。但是,目前我们只是避免使用数组。 – Arvodan 2010-10-04 09:36:15