Почему Point занимает меньше памяти, чем Integer

Я измеряю размеры объектов, проверяя, как долго их байтовые массивы используют ByteArrayOutputStream. При выполнении:

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

Они возвращают 81 и 51.

Я верю, что точка состоит из двух примитивов, но это, по-видимому, не является причиной.

Код я для Utils.getObjectSize:

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

EDIT:

Я выразил себя не так. Я действительно хотел знать, почему они берут больше размера в потоке.

Ответы

Ответ 1

Чтобы начать с строк java.lang.Integer, java.lang.Number и value появятся в результате сериализации для 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"
        // ...
    }
}

Ответ 2

Ваш подход для определения размера объектов фактически не измеряет, сколько места они занимают в памяти.

Point на самом деле займет больше памяти, чем Integer (для JVM с 4 байтами, с 8-байтовым выравниванием они будут одинаковыми) - это просто происходит с сериализацией меньшего размера, возможно, из-за иерархия наследования.

Ответ 3

Целое число больше для сериализации, потому что его родительский Number является Serializable. Если вы печатаете все текстовые байты в сериализации объектов, вы получаете

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

Однако родительский пункт не является Serializable и не сериализуется.

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

Также имя поля 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();

Используемый вами метод показывает, насколько велика сериализация объекта как байта [], а не насколько она велика в памяти. Стандартная сериализация Java не очень эффективна.

Целое число, вероятно, потребляет 16 + 4 байта, а точка, вероятно, потребляет 16 + 2 * 4 байта. Однако, как много JVMs выделяют на границе 8 байтов, вы, скорее всего, обнаружите, что они потребляют одинаковый объем памяти.

Причина, по которой Integer больше сериализуется, заключается в том, что Java сериализует не только объект, но и его родителей, а также перечисляет то, что они есть.

Ответ 4

Вы измеряете размер объекта, когда он сериализуется в потоке. Это не будет таким же, как размер объекта в памяти.