开发者

Why does Point take less memory than Integer

I'm measuring the sizes of objects by checking how long their byte arrays are using ByteArrayOutputStream. When doing:

System.out.println(Utils.getObjectSize(new Integer(123123)));
System.out.println(Utils.getObjectSize(new Point(123, 123)));

They return 81 and 51.

I belive P开发者_运维知识库oint consists of two primitives but that doesn't seem to be the reason.

The code I for Utils.getObjectSize:

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
ObjectOutputStream objectStream = new ObjectOutputStream(byteStream);
objectStream.writeObject(object);
objectStream.close();
return byteStream.toByteArray().length;

EDIT:

I expressed myself wrong. I actually wanted to know why they take more size in the stream.


To start with the strings java.lang.Integer, java.lang.Number and value appear in the serialization result for Integer. That should give a hint about why the serialization size is not very well correlated with the members of the object.

Here is some of the content of the resulting byte arrays listed: 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"
        // ...
    }
}


Your approach for finding the size of objects doesn't actually measure how much space they take up in memory at all.

Point will actually take more memory than Integer (for a 4-byte-aligned JVM; with 8 byte alignment they'll be the same) - it just happens to serialize to a smaller size, probably due to the inheritance hierarchy.


Integer is larger to serialise because its parent Number is Serializable. If you print all the text bytes in the object serialisation you get

....sr..java.lang.Integer.......8...I..valuexr..java.lang.Number...........xp....

However, Point's parent is not Serializable and is not serialized.

....sr..java.awt.Point...r4~.&...I..xI..yxp...{...{

Also Integer's field name is longer (slightly)

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();

The method you are using looks at how large is the Object serialisation as a byte[], not how large it is in memory. The standard Java serialisation is not very efficient.

Integer is likely to consume 16 + 4 bytes and Point is likely to consume 16 + 2 * 4 bytes. However as many JVMs allocate on a 8 byte boundary, you are likely to find they consume the same amount of memory.

The reason Integer is larger to serialize is that Java serializes not just the Object but its parents as well including listing what they are.


You're measuring the size of the object when it's serialized to a stream. That won't be the same as the size of the object in memory.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜