如何获取表示 Java 对象的序列化字节数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3938122/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:02:21  来源:igfitidea点击:

How to get amount of serialized bytes representing a Java object?

java

提问by Chris Redford

What syntax would I use to get the number of bytes representing a string and compare them to the number of bytes representing an ArrayListholding that string, for example?

例如,我将使用什么语法来获取表示字符串的字节数并将它们与表示ArrayList持有该字符串的字节数进行比较?

I am using a multi-agent agent system to send objects via messages and I want to keep track of how much space each message takes up. The method doesn't have to be dead-on accurate, as long as it scales proportionally to the actual size of the object. E.g. a Vector of strings of length 4 will report as smaller than a Vector of strings of length 5.

我正在使用多代理代理系统通过消息发送对象,我想跟踪每条消息占用的空间。该方法不必非常精确,只要它与对象的实际大小成比例地缩放即可。例如,长度为 4 的字符串向量将报告为小于长度为 5 的字符串向量。

回答by Vivin Paliath

You can convert your object into a byte array using ObjectOutputStreamand ByteArrayOutputStream:

您可以使用ObjectOutputStreamand将对象转换为字节数组ByteArrayOutputStream

public static int sizeof(Object obj) throws IOException {

    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);

    objectOutputStream.writeObject(obj);
    objectOutputStream.flush();
    objectOutputStream.close();

    return byteOutputStream.toByteArray().length;
}

I just tested this out. The object who's size you're trying to calculate, needs to implement Serializable(which means you may have to mark every object as such simply to get its size. Might not be desirable). I wrote a quick and dirty program to test this out:

我刚刚测试了这个。您尝试计算大小的对象需要实现Serializable(这意味着您可能必须将每个对象标记为这样才能获得其大小。可能不理想)。我写了一个快速而肮脏的程序来测试这个:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Sizeof {

    public static class Person implements Serializable {
        private String name;
        private String age;

        public Person(String name, String age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getAge() {
            return age;
        }

        public void setAge(String age) {
            this.age = age;
        }
    }

    public static void main(String[] args) {
        Person p1 = new Person("Alby", "20");
        Person p2 = new Person("VeryLongName", "100");
        String s1 = "This is it";
        String s2 = "This";

        try {
            System.out.println("p1 " + sizeof(p1));
            System.out.println("p2 " + sizeof(p2));
            System.out.println("s1 " + sizeof(s1));
            System.out.println("s2 " + sizeof(s2));                                 
        }

        catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static int sizeof(Object obj) throws IOException {

        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);

        objectOutputStream.writeObject(obj);
        objectOutputStream.flush();
        objectOutputStream.close();

        return byteOutputStream.toByteArray().length;
    }
}

Which gave me:

这给了我:

p1 85
p2 94
s1 17
s2 11

EDIT

编辑

Stephen C's answer highlights some caveats with this method.

Stephen C 的回答强调了这种方法的一些注意事项。

回答by mwk

I needed to check this accurately per-memcache write while investigating a server bug where memcache sizes were exceeded. To avoid the overhead of a big byte array for large objects I extended OutputStream as a counter:

在调查超出内存缓存大小的服务器错误时,我需要准确地检查每个内存缓存写入。为了避免大对象的大字节数组的开销,我将 OutputStream 扩展为计数器:

public class CheckSerializedSize extends OutputStream {

    /** Serialize obj and count the bytes */
    public static long getSerializedSize(Serializable obj) {
        try {
            CheckSerializedSize counter = new CheckSerializedSize();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(counter);
            objectOutputStream.writeObject(obj);
            objectOutputStream.close();
            return counter.getNBytes();
        } catch (Exception e) {
            // Serialization failed
            return -1;
        }
    }

    private long nBytes = 0;

    private CheckSerializedSize() {}

    @Override
    public void write(int b) throws IOException {
        ++nBytes;
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        nBytes += len;
    }

    public long getNBytes() {
        return nBytes;
    }
}

回答by Burleigh Bear

You can serialise each object into arrays and compare the length of each array. This is not very accurate, in the general case, but often gives a good approximation.

您可以将每个对象序列化为数组并比较每个数组的长度。在一般情况下,这不是很准确,但通常会给出一个很好的近似值。

Have a look at ObjectOutputStream (which can be used to serialise an object and turn it into Bytes) and ByteArrayOutputStream (which can be used to hold the serialised bytes).

看看 ObjectOutputStream(可用于序列化对象并将其转换为字节)和 ByteArrayOutputStream(可用于保存序列化的字节)。

回答by Stephen C

I don't think you've got much choice but to modify your code so that it measures the message sizes at runtime.

我认为除了修改代码以在运行时测量消息大小外,您别无选择。

You could just serialize example objects and capture and measure the serialized size. This has the following problems:

您可以只序列化示例对象并捕获和测量序列化的大小。这有以下问题:

  • You can never be sure that the objects are typical.
  • Various aggregation effects mean that it is hard to deduce the size of a message from the serialized size of its component objects. (For instance, class signatures are only encoded once per serialization.)
  • This approach tells you nothing about the relative frequency of different message types.
  • 您永远无法确定这些对象是典型的。
  • 各种聚合效应意味着很难从其组件对象的序列化大小推断消息的大小。(例如,类签名每次序列化只编码一次。)
  • 这种方法不会告诉您不同消息类型的相对频率。

If you can manage this, you will get more accurate results if you can measure the actual messages. This would most likely entail modifying the agent framework to count, measure and (ideally) classify messages into different kinds. The framework might already have hooks for doing this.

如果您可以管理这一点,如果您可以衡量实际消息,您将获得更准确的结果。这很可能需要修改代理框架以对消息进行计数、测量和(理想情况下)将消息分类为不同类型。该框架可能已经具有用于执行此操作的钩子。

The method doesn't have to be dead-on accurate, as long as it scales proportionally to the actual size of the object. E.g. a Vector of strings of length 4 will report as larger than a Vector of strings of length 5.

该方法不必非常精确,只要它与对象的实际大小成比例地缩放即可。例如,长度为 4 的字符串向量将报告为大于长度为 5 的字符串向量。

(I assume that you meant smaller than...)

(我假设你的意思是小于......)

Your example illustrates one of the problems of trying to estimate serialized object sizes. A serialization of a Vector<String>of size 4 could be smaller ... or larger ... that a Vector<String>of size 5. It depends on what the String values are. Additionally, if a message contains two Vector<String>objects, the serialized size occupied by the vectors will be less that sum of the sizes of the two vectors when they are serialized separately.

您的示例说明了尝试估计序列化对象大小的问题之一。Vector<String>大小为 4的 a的序列化可能Vector<String>比大小为 5 的a 更小……或更大……这取决于字符串值是什么。此外,如果一条消息包含两个Vector<String>对象,则向量占用的序列化大小将小于两个向量分别序列化时的大小之和。

回答by Steven

have a look at: http://www.javaworld.com/javaworld/javaqa/2003-12/02-qa-1226-sizeof.html

看看:http: //www.javaworld.com/javaworld/javaqa/2003-12/02-qa-1226-sizeof.html

closest thing that comes to mind would be serializing it and reading the num of bytes

想到的最接近的事情是序列化它并读取字节数

回答by Amit Nema

You can check the size of object after serialization process using Apache Commonsas follows:

您可以使用Apache Commons在序列化过程后检查对象的大小,如下所示:

    // Create serialize objects.
    final List<String> src = new ArrayList<String>();
    src.add("awsome");
    src.add("stack");
    src.add("overflow");

    System.out.println(
            "Size after serialization:" + SerializationUtils.serialize((Serializable) src).length);

Output :

输出 :

Size after serialization:86