为什么Point占用的内存少于Integer

Rob*_*Fox 14 java memory

我通过检查字节数组使用ByteArrayOutputStream多长时间来测量对象的大小.做的时候:

System.out.println(Utils.getObjectSize(new Integer(123123)));
System.out.println(Utils.getObjectSize(new Point(123, 123)));
Run Code Online (Sandbox Code Playgroud)

他们回归81和51.

我相信Point由两个原语组成,但这似乎不是原因.

Utils.getObjectSize的代码I:

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
ObjectOutputStream objectStream = new ObjectOutputStream(byteStream);
objectStream.writeObject(object);
objectStream.close();
return byteStream.toByteArray().length;
Run Code Online (Sandbox Code Playgroud)

编辑:

我表达自己错了.我其实想知道为什么他们在流中占用更多的大小.

aio*_*obe 8

从字符串开始java.lang.Integer,java.lang.Numbervalue出现在序列化结果中Integer.这应该暗示为什么序列化大小与对象的成员没有很好的相关性.

以下是列出的结果字节数组的一些内容:http://ideone.com/ragKZ

import java.awt.Point;
import java.io.*;

class Test {

    public static byte[] getBytes(Object object) throws IOException {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        ObjectOutputStream objectStream = new ObjectOutputStream(byteStream);
        objectStream.writeObject(object);
        objectStream.close();
        return byteStream.toByteArray(); 
    }

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

        byte[] iBytes = getBytes(new Integer(123123));
        System.out.println(new String(iBytes,  8, 17)); // "java.lang.Integer"
        System.out.println(new String(iBytes, 39,  5)); // "value"
        System.out.println(new String(iBytes, 48, 16)); // "java.lang.Number"
        // ...

        byte[] pBytes = getBytes(new Point(123, 123));
        System.out.println(new String(pBytes, 8, 14));  // "java.awt.Point"
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果你关心的是有效地打包数据,我不认为使用对象流是推荐的方法.不能说我在这方面很有经验. (3认同)

Jon*_*eet 7

您找到对象大小的方法实际上并不能测量它们在内存中占用多少空间.

Point实际上将占用更多的内存Integer(对于4字节对齐的JVM; 8字节对齐它们将是相同的) - 它恰好序列化为更小的大小,可能是由于继承层次结构.

  • 如果您有一个具有8字节边界的JVM进行分配,它们的大小将相同.例如OpenJDK这样做. (2认同)

Pet*_*rey 5

由于其父级Number是Serializable ,因此序列化的整数更大.如果您打印对象序列化中的所有文本字节

....sr..java.lang.Integer.......8...I..valuexr..java.lang.Number...........xp....
Run Code Online (Sandbox Code Playgroud)

但是,Point的父级不是Serializable,也不是序列化的.

....sr..java.awt.Point...r4~.&...I..xI..yxp...{...{
Run Code Online (Sandbox Code Playgroud)

Integer的字段名称也更长(略)

byte[] bytes = byteStream.toByteArray();
for(int i=0;i<bytes.length;i++) {
    char ch = (char) bytes[i];
    if (ch >= ' ' && ch < 127)
        System.out.print(ch);
    else
        System.out.print('.');
}
System.out.println();
Run Code Online (Sandbox Code Playgroud)

您正在使用的方法将查看Object序列化作为byte []的大小,而不是内存中的大小.标准的Java序列化效率不高.

整数可能消耗16 + 4个字节,而Point可能消耗16 + 2*4个字节.但是,由于许多JVM在8字节边界上分配,您可能会发现它们消耗的内存量相同.

Integer更大的序列化原因是Java不仅序列化了Object,还将其父序列化,包括列出它们的内容.