为什么Joda Time序列化形式这么大,怎么办呢?

Mik*_*Hay 4 java serialization jodatime

在我的机器上,以下代码段:

DateTime now = DateTime.now();
System.out.println(now);
System.out.println("Date size:\t\t"+serialiseToArray(now).length);
System.out.println("DateString size:\t"+serialiseToArray(now.toString()).length);
System.out.println("java.util.Date size:\t"+serialiseToArray(new Date()).length);
Duration twoHours = Duration.standardHours(2);
System.out.println(twoHours);
System.out.println("Duration size:\t\t"+serialiseToArray(twoHours).length);
System.out.println("DurationString size:\t"+serialiseToArray(twoHours.toString()).length);
Run Code Online (Sandbox Code Playgroud)

给出以下输出:

2013-09-09T15:07:44.642+01:00
Date size:      273
DateString size:    36
java.util.Date size:    46
PT7200S
Duration size:      107
DurationString size:    14
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,org.joda.time.DateTime对象比它的String形式大5倍以上,它似乎完美地描述了它,并且java.util.Date等价.表示2小时的Duration对象也比我预期的要大得多,因为查看源它似乎唯一的成员变量是单个long值.

为什么这些序列化对象如此之大?是否有任何预先存在的解决方案来获得更小的代表?

serialiseToArray方法,供参考:

private static byte[] serialiseToArray(Serializable s)
{
    try
    {
        ByteArrayOutputStream byteArrayBuffer = new ByteArrayOutputStream();
        new ObjectOutputStream(byteArrayBuffer).writeObject(s);
        return byteArrayBuffer.toByteArray();
    }
    catch (IOException ex)
    {
        throw new RuntimeException(ex);
    }
}
Run Code Online (Sandbox Code Playgroud)

Joa*_*uer 7

序列化有一些开销.在这种情况下,您最常注意到的开销是在实际输出中描述了类结构.并且由于Duration有一个基类(BaseDuration)和两个接口(ReadableDurationSerializable),这个开销变得略大于Date(没有基类和单个接口).

这些类是使用序列化文件中的完全限定类名引用的,因此创建了相当多的字节.

好消息:每个输出流只支付一次开销.如果序列化另一个Duration对象,则大小差异应该相当小.

我已经使用jdeserialize项目来查看序列化a java.util.Date与a 的结果Duration(请注意,此工具不需要访问.class文件,因此它转储的所有信息实际上都包含在序列化数据中):

结果java.util.Date如下:

read: java.util.Date _h0x7e0001 = r_0x7e0000;
//// BEGIN stream content output
java.util.Date _h0x7e0001 = r_0x7e0000;
//// END stream content output

//// BEGIN class declarations (excluding array classes)
class java.util.Date implements java.io.Serializable {
}

//// END class declarations

//// BEGIN instance dump
[instance 0x7e0001: 0x7e0000/java.util.Date
  object annotations:
    java.util.Date
        [blockdata 0x00: 8 bytes]

  field data:
    0x7e0000/java.util.Date:
]
//// END instance dump

结果Duration如下:

read: org.joda.time.Duration _h0x7e0002 = r_0x7e0000;
//// BEGIN stream content output
org.joda.time.Duration _h0x7e0002 = r_0x7e0000;
//// END stream content output

//// BEGIN class declarations (excluding array classes)
class org.joda.time.Duration extends org.joda.time.base.BaseDuration implements java.io.Serializable {
}

class org.joda.time.base.BaseDuration implements java.io.Serializable {
    long iMillis;
}

//// END class declarations

//// BEGIN instance dump
[instance 0x7e0002: 0x7e0000/org.joda.time.Duration
  field data:
    0x7e0001/org.joda.time.base.BaseDuration:
        iMillis: 0
    0x7e0000/org.joda.time.Duration:
]
//// END instance dump

请注意,"类声明"块的长度要长得多Duration.这也解释了为什么序列化单个 Duration需要107个字节,但序列化两个(不同的)Duration对象只需要121个字节.