0

有两个程序集:
1)包含序列化程序的程序集。这是序列化和反序列化开始的地方。
2) 包含序列化类型的程序集。这是从第一个程序集调用序列化程序的地方。
assembly1 中的序列化程序的想法很简单。它有两种方法用于将对象从字节数组转换为字节数组。该序列化程序的客户端代码如下所示:

    ISerializer serializer = ...

    MyClass my = new MyClass();
    byte[] data = serializer.Serialize(my);
    Console.WriteLine(Encoding.ASCII.GetString(data)); // dump serialized form
    MyClass another = (MyClass)serializer.Deserialize(data);

MyClass 是在 assembly2 中定义的,因此 assembly1 对此一无所知。如果序列化器是用标准的 .Net 类实现的,那么该场景将起作用,如下所示:

public class DotNetSerializer : ISerializer
{
    public byte[] Serialize(object obj)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        using (MemoryStream stream = new MemoryStream())
        {
            formatter.Serialize(stream, obj);
            byte[] result = stream.GetBuffer();
            Array.Resize(ref result, (int)stream.Length);
            return result;
        }
    }

    public object Deserialize(byte[] data)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        using (Stream stream = new MemoryStream(data))
        {
            return formatter.Deserialize(stream);
        }
    }
}

MyClass 的序列化形式将包含有关定义 MyClass 的程序集的信息。但是,如果序列化器将使用 Java 的类(使用 IKVM 转换)来实现,那么在反序列化期间将抛出 ClassNotFound 异常。这是一个使用 Java 类的序列化器实现:

public class JavaSerializer : ISerializer
{
    public object Deserialize(byte[] data)
    {
        ByteArrayInputStream stream = new ByteArrayInputStream(data);
        ObjectInputStream ois = new ObjectInputStream(stream);
        return ois.readObject();
    }

    public byte[] Serialize(object obj)
    {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(stream);
        oos.writeObject(obj);
        stream.flush();
        return stream.toByteArray();
    }
}

这在 .Net 中不起作用,但如果从 Eclipse 加载插件清单中的附加条目(例如 BuddyPolicy 和 RegisterBuddy),则在 Java 中可以正常工作。我不能只从 JavaSerializer 切换到 DotNetSerializer,因为在我的应用程序(主要用 Java 编写)中有很多 readObject、writeObject、readResolve 等......但我需要以某种方式解决这个问题,所以我寻求解决方案. 目前我看到了一些假设的解决方法:

  • 重载 ObjectOutputStream 的某些方法,因此 MyClass 的序列化形式也将包含程序集名称,例如“MyClass,MyAssembly,...”。
  • 重载 ObjectInputStream 中的某些方法,因此类将以某种不同的方式加载,也许应该在某些不同的程序集中进行搜索,等等。
  • 向程序集清单添加一些信息,以便 IKVM 知道在哪里搜索 MyClass。这是真的吗?这个问题应该如何解决?
4

1 回答 1

0

IKVM 团队的人给了我答案:

1)您可以子类 ObjectOutputStream 并覆盖 annotateClass 来编写程序集名称和子类 ObjectInputStream 并覆盖 resolveClass 来读取程序集名称。

2) 将以下自定义属性添加到执行反序列化的程序集:[程序集:IKVM.Attributes.CustomAssemblyClassLoader(typeof(ikvm.runtime.AppDomainAssemblyClassLoader))]

我还发现我可以在应用程序配置文件中使用显式设置覆盖任何程序集的类加载器:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="ikvm-classloader:MyExampleAssembly" value="ikvm.runtime.AppDomainAssemblyClassLoader, IKVM.OpenJDK.ClassLibrary, Version=0.37.0.0, Culture=neutral, PublicKeyToken=null" />
  </appSettings>
</configuration>

当使用-classloader 命令行参数时,它也可以在从java jar 转换过程中设置。

于 2009-06-17T03:44:55.057 回答