Почему 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
Вы измеряете размер объекта, когда он сериализуется в потоке. Это не будет таким же, как размер объекта в памяти.