簡體   English   中英

如何獲取表示Java對象的序列化字節數?

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

我將使用什么語法來獲取表示字符串的字節數,並將它們與表示保存該字符串的ArrayList的字節數進行比較,例如?

我正在使用多代理代理系統通過消息發送對象,我想跟蹤每條消息占用多少空間。 只要該方法與對象的實際大小成比例地縮放,該方法就不必是准確的。 例如,長度為4的字符串向量將報告為小於長度為5的字符串向量。

您可以使用ObjectOutputStreamByteArrayOutputStream將對象轉換為字節數組:

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;
}

我剛測試了這個。 你想要計算的大小的對象需要實現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;
    }
}

哪個給了我:

p1 85
p2 94
s1 17
s2 11

編輯

Stephen C的回答強調了這種方法的一些注意事項。

在調查超出memcache大小的服務器錯誤時,我需要准確地檢查每個memcache。 為了避免大對象的大字節數組的開銷,我將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;
    }
}

您可以將每個對象序列化為數組並比較每個數組的長度。 在一般情況下,這不是非常准確,但通常給出了很好的近似值。

查看ObjectOutputStream(可用於序列化對象並將其轉換為Bytes)和ByteArrayOutputStream(可用於保存序列化字節)。

我認為你沒有太多選擇,只能修改你的代碼,以便它在運行時測量消息大小。

您可以序列化示例對象並捕獲和測量序列化大小。 這有以下問題:

  • 您永遠無法確定對象是否典型。
  • 各種聚合效果意味着很難從其組件對象的序列化大小推斷出消息的大小。 (例如,類簽名每個序列化只編碼一次。)
  • 此方法不會告訴您有關不同消息類型的相對頻率的信息。

如果您可以對此進行管理,那么如果您可以測量實際消息,您將獲得更准確的結果。 這很可能需要修改代理框架以計算,測量和(理想地)將消息分類為不同類型 框架可能已經有了鈎子來做這件事。

只要該方法與對象的實際大小成比例地縮放,該方法就不必是准確的。 例如,長度為4的字符串向量將報告為長度為5的字符串向量。

(我認為你的意思是小於 ...)

您的示例說明了嘗試估計序列化對象大小的問題之一。 大小為4的Vector<String>的序列化可能更小......或者更大......一個大小為5的Vector<String> 。它取決於String值是什么。 此外,如果消息包含兩個Vector<String>對象,則向量占用的序列化大小將小於單獨序列化時兩個向量的大小總和。

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

我想到的最接近的事情就是將它序列化並讀取字節數

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM