对象是否可能在重新序列化后具有不同的字节大小?



在Java中,我创建了一个对象,将其序列化为一个长度为642字节的数组,然后将其返回为一个对象,对该对象进行序列化,并得到一个长度为651字节的数组。这是怎么发生的,为什么会发生?我认为对象的长度应该与重复序列化一致,因为长度在我序列化和反序列化的其他对象中是相同的。请注意,在随后的反序列化和重新序列化之后,长度仍然是651字节。

下面是我的代码:
PrivateIPV4_Reliable object = new PrivateIPV4_Reliable();
final byte[] data = ByteArrays.ObjectToByteArray(object);
AppTester.print("Serialized an PrivateIPV4_Reliable of size: " + data.length); 
// 642 bytes
PrivateIPV4_Reliable deSerialzed = (PrivateIPV4_Reliable) ByteArrays.MakeByteArrayIntoObject(data);
byte[] deserializedBytes = ByteArrays.ObjectToByteArray(deSerialzed);
AppTester.print("Reserialized it into object of length: " + deserializedBytes.length + "n"); 
// 651 bytes
// Why does the object get bigger after re-serialization?
// This size increase did not happen with another object that I serialized and de-serialized.

* Update 1 *

以下是十六进制格式的字节数组:

第一次序列化后的字节数组:(length: 642)

ACED000573720022436F72655F52656C6961626C652E50726976617465495056345F52656C6961626C65001691657B307FB102000349000D6D7950726976617465506F72744A00166D7954696D654F66496E7374616E74696174696F6E5F5B00136D79507269766174654164647265737365735F7400175B4C6A6176612F6E65742F496E6574416464726573733B78700000D2B50000014EC8CD8315757200175B4C6A6176612E6E65742E496E6574416464726573733B38E6AD91E5D9DA88020000787000000005737200156A6176612E6E65742E496E657436416464726573735F7C2081522C802103000549000873636F70655F69645A000 c73636f70655f69645f7365745a001073636f70655f69666e616d655f7365744c000669666e616d657400124c6a6176612f6c616e672f537472696e673b5b00096970616464726573737400025b42787200146a6176612e6e65742e496e6574416464726573732d9b57af9fe3ebdb0300034900076164647265737349000666616d696c794c0008686f73744e616d6571007e0006787000000000000000027078000000030101740005776c616e30757200025b42acf317f8060854e00200007870000000102602030a2e0a9d900000000000000045787371007e00050000000000000002707800000003010171007e000a7571007e000b000000102602030 a2e0a9d90a28869fffe31331e787371007e00050000000000000002707800000003010171007e000a7571007e000b00000010fe80000000000000a28869fffe31331e787371007e00050000000000000002707800000003010171007e000a7571007e000b000000102602030a2e0a9d90e9958cbc64d3b80b787371007e0008c0a8014f000000027078

第二次序列化后的字节数组:(length: 651)

ACED000573720022436F72655F52656C6961626C652E50726976617465495056345F52656C6961626C65001691657B307FB102000349000D6D7950726976617465506F72744A00166D7954696D654F66496E7374616E74696174696F6E5F5B00136D79507269766174654164647265737365735F7400175B4C6A6176612F6E65742F496E6574416464726573733B78700000D2B50000014EC8CD8315757200175B4C6A6176612E6E65742E496E6574416464726573733B38E6AD91E5D9DA88020000787000000005737200156A6176612E6E65742E496E657436416464726573735F7C2081522C802103000549000873636F70655F69645A000 c73636f70655f69645f7365745a001073636f70655f69666e616d655f7365744c000669666e616d657400124c6a6176612f6c616e672f537472696e673b5b00096970616464726573737400025b42787200146a6176612e6e65742e496e6574416464726573732d9b57af9fe3ebdb0300034900076164647265737349000666616d696c794c0008686f73744e616d6571007e0006787000000000000000027078000000030101740005776c616e30757200025b42acf317f8060854e00200007870000000102602030a2e0a9d900000000000000045787371007e000500000000000000027078000000030101740005776c616e307571007e000 b000000102602030a2e0a9d90a28869fffe31331e787371007e000500000000000000027078000000030101740005776c616e307571007e000b00000010fe80000000000000a28869fffe31331e787371007e000500000000000000027078000000030101740005776c616e307571007e000b000000102602030a2e0a9d90e9958cbc64d3b80b787371007e0008c0a8014f000000027078

第三次序列化后的字节数组(长度:651,与第二次序列化相同)

* Update 2 *

这是正在序列化/反序列化的对象:

package Core_Reliable;
import Utilities.AppTester;
import Utilities.ByteArrays;
import java.io.Serializable;
import java.net.InetAddress;
/**
 * @author johnmichaelreed2
 */
public final class PrivateIPV4_Reliable implements Serializable {
    private static final long serialVersionUID = 6352314532134833L;
    private final InetAddress[] myPrivateAddresses_;
    private final int myPrivatePort;
    private final long myTimeOfInstantiation_;
    public PrivateIPV4_Reliable(InetAddress privateIPs[], int privatePort) {
        AppTester.check(privateIPs != null, "No null values in initializer.");
        this.myPrivateAddresses_ = privateIPs;
        this.myPrivatePort = privatePort;
        this.myTimeOfInstantiation_ = System.currentTimeMillis();
    }
    public boolean deepEquals(PrivateIPV4_Reliable other) {
        return ByteArrays.deepEquals(this, other);
    }
    public InetAddress getCopyOfInetAddressNumber(int index) {
        InetAddress copy = ByteArrays.tryDeepCopy(this.myPrivateAddresses_[index]);
        AppTester.check(copy != null, "Failed to deep copy my InetAddress");
        AppTester.check(copy instanceof InetAddress, "The copy isn't an InetAddress");
        return copy;
    }
    public InetAddress[] getInetAddressesCopy() {
        AppTester.check(myPrivateAddresses_ != null, "No null private address lists.");
        return ByteArrays.tryDeepCopy(myPrivateAddresses_);
    }
    public int getPrivatePort() {
        return myPrivatePort;
    }
    public long getTimeAtInstantiation() {
        return myTimeOfInstantiation_;
    }
}
下面是我用于序列化的方法:
public static byte[] ObjectToByteArray(final Object object) {
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.flush();
        oos.writeObject(object);
        oos.flush();
        oos.close();
        // get the byte array of the object
        byte[] obj = baos.toByteArray();
        baos.flush();
        baos.close();
        return obj;
    } catch (Exception e) {
        AppTester.printEx(e);
        System.exit(-78);
        return null;
    }
}

下面是我用来反序列化的方法:

public static Object makeByteArrayIntoObject(byte[] data) {
    AppTester.check(data != null, "Null data");
    Object to_return = null;
    try(ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) {
        try {
            to_return = ois.readObject();
        } catch (ClassNotFoundException cnfe) {
            AppTester.printEx(cnfe);
        } catch(StreamCorruptedException sce) {
            AppTester.printEx(sce);
        }
    } catch (IOException ioe) {
        AppTester.printEx(ioe);
    } finally {
        return to_return;
    }
}

其中"AppTester"是我的自定义日志/调试/断言类。(见JohnsAppTester)

确定导致问题的原因的唯一方法是使用某种工具将序列化的两个版本作为字节流进行比较,然后根据规范所述手动反转序列化。

然而,一种可能性是在原始序列化和重新序列化之间对PrivateIPV4_Reliable类进行了"二进制兼容"更改。如果您怀疑该类有多个版本,那么可以解释它。

请注意,Java对象序列化协议/格式不能保证序列化是相同的。

相关内容

  • 没有找到相关文章

最新更新