【问题标题】:Deserializable exception : local class is not compatible cause of serialVersionID可反序列化异常:本地类不兼容导致 serialVersionuID
【发布时间】:2014-11-11 02:25:26
【问题描述】:

这是我的代码:

MyOwnObject deserializedObject = null;
try{
    ByteArrayInputStream bis = new ByteArrayInputStream(serializedObject.getBytes());
    ObjectInputStream ois= new ObjectInputStream(bis);
    deserializedObject = (MyOwnObject)ois.readObject();
    ois.close();
}catch(Exception e){
    e.printStackTrace();
}

someMapper.insert(deserializedObject);

PS:serializedObject 是我之前从序列化过程中得到的一个字符串,我认为它运行良好。

代码抛出异常:

local class incompatible: stream classdesc serialVersionUID = 1360826667802527544, local class serialVersionUID = 1360826667806852920

在堆栈跟踪中,有一些关于我的对象中某些属性的类型 Integer 的信息。

更新: serializeObject 是一个字符串,来自这段代码:

try {
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    ObjectOutputStream so = new ObjectOutputStream(bo);
    so.writeObject(myObject);
    so.flush();
    serializedObject = bo.toString();
}catch (Exception e) {
    System.out.println(e);
}

回答:

    //Serialization from object to string
    String serializedObject="";
    try{
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        oos.flush();
        serializedObject = new String(Base64.encode(baos.toByteArray()));
        oos.close();
    }catch(Exception e){
        e.printStackTrace();
    }


    //Deserialization from string to object
    MyOwnObject deserializedObject = null;
    try{
        byte[] bytes = Base64.decode(serializedObject.getBytes());
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        deserializedObject = (MyOwnObject)ois.readObject();
        ois.close();
    }catch(Exception e){
        e.printStackTrace();
    }

从这里,我可以使用deserializedObject作为对象,效果很好!

【问题讨论】:

  • serializedObject 是什么以及如何创建?
  • 它来自 ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream so = new ObjectOutputStream(bo);所以.writeObject(myObject);所以.flush(); serializedObject = bo.toString();
  • serializedObject 是一个字符串:这可能是问题所在。对象被序列化为字节,而不是字符。不要将二进制字节转换为字符串。
  • @NicoPratama 您应该使用serializedObject 的详细信息编辑您的问题,而不是在评论中添加它。
  • 这是一个错误的方法。但是请参阅我编辑的答案,最后我提到了如何从序列化对象创建String

标签: java spring exception serialization stream


【解决方案1】:

除了base64,你也可以使用十六进制字符串!遇到类似问题我总是使用它!

【讨论】:

    【解决方案2】:

    问题在于如何创建serializedObject

    您使用ByteArrayOutputStream。你不应该打电话给toString()。而是调用它的toByteArray() 方法来获取作为字节数组的底层数据,您可以使用它来创建您的ByteArrayInputStream,它会起作用。

    例子:

    // Serialization
    ByteArrayOutputStream bo = new ByteArrayOutputStream();
    ObjectOutputStream so = new ObjectOutputStream(bo);
    so.writeObject(myObject);
    so.flush();
    byte[] serializedObject = bo.toByteArray();
    
    // Deserialization
    MyOwnObject deserializedObject = null;
    try {
        ByteArrayInputStream bis = new ByteArrayInputStream(serializedObject);
        ObjectInputStream ois = new ObjectInputStream(bis);
        deserializedObject = (MyOwnObject)ois.readObject();
        ois.close();
    } catch (Exception e){
        e.printStackTrace();
    }
    

    序列化对象是字节序列(字节数组)而不是字符序列。您不能从序列化对象的字节创建String,因为它可能不包含例如有效的 unicode 代码点。

    如果您确实需要将序列化对象表示为String,请尝试在hex string 中表示字节数组或使用base64 encoding

    【讨论】:

    • 我到处都看到使用 base64 来解决这个问题,这是最好的选择吗?我将把 serializedObject 字符串发送到队列中(JMS w/Apache ActiveMQ),然后再使用它并重建一个对象以供进一步使用..
    • 在这种情况下,检查软件/代码的文档是什么预期的,在这种情况下,您显然别无选择,只能创建所需的表单。
    • 如果您将成为读取消息并反序列化对象的人,那么决定权在您手中。两种方法(十六进制字符串和 base64)在任何情况下都可以使用。如果您的对象很小,则十六进制字符串会更快。如果你的对象很大,base64 会产生更小的字符串。所以你决定。
    • 我使用base 64,尽管通过MQ发送的字符串是不可读的并且类似于一些哈希码,但重要的是字符串可以发送并且可以转换回对象..谢谢@icza!
    猜你喜欢
    • 2012-01-28
    • 2014-11-10
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 2021-02-16
    • 2018-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多