Ste*_* K. 15 java serialization scala
要增强群集中的消息传递,重要的是要在运行时了解消息的大小(我应该更喜欢处理本地消息还是远程消息).
我可以找到基于java检测估计对象内存大小的框架.我测试了classmexer,它没有接近序列化大小和sourceforge SizeOf.
在一个小的测试用例中,SizeOf错误大约10%,比序列化快10倍.(仍然瞬态完全破坏了估计,因为例如ArrayList是瞬态的,但是被序列化为数组,修补SizeOf并不容易.但我可以忍受这种情况)
另一方面,10%的误差和10%的误差似乎不太好.任何想法我怎么能做得更好?
更新:我还测试了ObjectSize(http://sourceforge.net/projects/objectsize-java).结果似乎只适合非继承对象:(
类在运行时获取的大小不一定与其在内存中的大小有关.你提到的例子是瞬态场.其他示例包括对象何时实现Externalizable并自行处理序列化.
如果一个对象实现了Externalizable或者提供readObject()
/ writeObject()
然后你最好的选择是将对象序列化到一个内存缓冲区来找出大小.它不会很快,但它会准确.
如果对象使用默认序列化,则可以修改SizeOf以考虑瞬态字段.
序列化许多相同类型的对象后,您可以为该类型构建"序列化配置文件",将序列化大小与SizeOf的运行时大小相关联.这样您就可以快速估计序列化大小(使用SizeOf),然后将其与运行时大小相关联,以获得比SizeOf提供的结果更准确的结果.
其他答案中有许多好处,缺少的一点是序列化机制可能会缓存某些对象.
例如,您序列化一系列对象A,B和C,这些对象在每个对象中包含两个对象o1和o2.让我们说对象开销是100个字节,让我们说对象看起来像:
Object shared = new Object();
Object shread2 = new Object();
A.o1 = new Object()
A.o2 = shared
B.o1 = shared2
B.o2 = shared
C.o1 = shared2
C.o2 = shared
Run Code Online (Sandbox Code Playgroud)
为简单起见,我们可以说通用对象需要50个字节来串行化,A的序列化大小为100(开销)+ 50(o1)+ 50(o2)= 200个字节.人们也可以对B和C做出类似的天真估计.但是,如果在调用reset之前所有三个都被相同的对象输出流序列化,那么你将在流中看到的是A和o1和o2的序列化,然后是b的序列化和o的b,但是因为它引用了o2是已经序列化的同一个对象.所以假设一个对象引用需要16个字节,B的大小现在是100(开销)+ 50(o1)+ 16(o2的参考)= 166.所以序列化所需的大小现在已经改变了! 我们可以对C进行同步计算,并且缓存两个对象得到132个字节,因此所有三个对象的序列化大小不同,最大和最小之间的差异为~33%.
因此,除非在每次难以准确估计序列化对象所需的大小时都没有缓存序列化整个对象.