在我的机器上,以下代码段:
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);
提供以下输出:
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
正如您所看到的,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);
}
}
答案 0 :(得分:7)
序列化有一些开销。在这种情况下,您最常注意到的开销是在实际输出中描述了类结构。由于Duration
具有基类(BaseDuration
)和两个接口(ReadableDuration
和Serializable
),因此该开销略大于Date
的开销(它没有基类,只有一个接口。)
使用序列化文件中的完全限定类名引用这些类,因此创建了相当多的字节。
好消息:每个输出流只支付一次开销。如果序列化另一个Duration
对象,则大小差异应该相当小。
我已使用the jdeserialize project查看序列化java.util.Date
与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个字节。
答案 1 :(得分:1)
来自the source:
在内部,该类包含两个数据。首先,它持有 datetime为1970-01-01T00:00:00Z的Java纪元的毫秒数。 其次,它拥有一个年代表,它决定了毫秒级 即时值转换为日期时间字段。默认 年表是org.joda.time.chrono.ISOChronology,这是商定的 国际标准,与现代格里高利兼容 日历。
ISOChronology源自AssembledChronology,其中大多数(但不是全部)被声明为瞬态场。