gpt4 book ai didi

java - 为什么Java序列化占用这么大的空间?

转载 作者:行者123 更新时间:2023-12-03 06:12:38 24 4
gpt4 key购买 nike

我尝试序列化 Byte 和 Integer 的实例,当另一端收到它们时,它们占用了多少空间,这让我感到震惊。为什么创建一个 Integer 只需要 4 个字节,但序列化后却占用了 10 倍以上的字节数?我的意思是在 C++ 中,final 类有一个 64 位类标识符及其内容。按照这个逻辑,我希望整数在序列化时占用 64 + 32,即 96 位。

import java.io.*;

public class Test {
public static void main (String[] ar) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(new Integer(32));
byte[] yourBytes = bos.toByteArray();
System.out.println("length: " + yourBytes.length + " bytes");
}
}

输出:

长度:81字节

更新:

public static void main(String[] args) throws IOException {

{
ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
ObjectOutput out1 = new ObjectOutputStream(bos1);
out1.writeObject(new Boolean(false));
byte[] yourBytes = bos1.toByteArray();
System.out.println("1 Boolean length: " + yourBytes.length);
}

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
for (int i = 0; i < 1000; ++i) {
out.writeObject(new Boolean(true)); // 47 bytes
}
byte[] yourBytes = bos.toByteArray();
System.out.println("1000 Booleans length: " + yourBytes.length); // 7040 bytes

final int count = 1000;

ArrayList<Boolean> listBoolean = new ArrayList<>(count);
listBoolean.addAll(Collections.nCopies(count, Boolean.TRUE));
System.out.printf("ArrayList: %d%n", sizeOf(listBoolean)); // 5096 bytes

Boolean[] arrayBoolean = new Boolean[count];
Arrays.fill(arrayBoolean, true);
System.out.printf("Boolean[]: %d%n", sizeOf(arrayBoolean)); // 5083 bytes

boolean[] array = new boolean[count];
Arrays.fill(array, true);
System.out.printf("boolean[]: %d%n", sizeOf(array)); // 1027 bytes

BitSet bits = new BitSet(count);
bits.set(0, count);
System.out.printf("BitSet: %d%n", sizeOf(bits)); // 201 bytes
}

static int sizeOf(Serializable obj) throws IOException {
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
ObjectOutputStream objsOut = new ObjectOutputStream(bytesOut);
objsOut.writeObject(obj);
return bytesOut.toByteArray().length;
}

输出:

1 boolean 值长度:47(每个 boolean 值 47 个字节)

1000 个 boolean 值长度:7040(每个 boolean 值 7 个字节)

ArrayList:5096(每个 boolean 值 5 个字节)

boolean 值[]:5083(每个 boolean 值 5 个字节)

boolean 值[]:1027(每个 boolean 值 1 个字节)

BitSet:201(每个 boolean 值 1 字节的 1/5)

最佳答案

虽然Radiodef已经阐明了为什么序列化对象的大小很大,但我想在这里提出另一点,这样我们就不会忘记底层java序列化算法中存在的优化(几乎在所有算法中)。

当您编写另一个 Integer 对象(或任何已编写的对象)时,在这种情况下您不会看到类似的大小(我的意思是大小不会是 81 * 2 = 162 字节),

ObjectOutput out = new ObjectOutputStream(bos);   
out.writeObject(new Integer(32));
out.writeObject(new Integer(65));
byte[] yourBytes = bos.toByteArray();
System.out.println("length: " + yourBytes.length + " bytes");

它的工作方式是,当类的实例(对象)第一次被请求序列化时,它会写入整个类的信息。即包括类名,它写入类中存在的每个字段的名称。这就是字节数更多的原因。这基本上是为了妥善处理类(class)评估案件。

当它第一次发送类的元数据时,它还会将相同的信息缓存到称为值缓存或间接表的本地缓存中。因此,下次当请求同一类的另一个实例进行序列化时(请记住,缓存仅适用于流级别,或在调用 Reset() 之前),它只写入一个标记(仅 4 个字节的信息),以便大小会更少。

关于java - 为什么Java序列化占用这么大的空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30746784/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com