Подтвердить что ты не робот

Размер файла по сравнению с размером памяти в Java

Если я возьму XML файл, который находится вокруг 2kB на диске, и загрузите содержимое в виде строки в память на Java, а затем измерьте размер объекта вокруг 33kB.

Почему огромный рост размера?
Если я делаю то же самое в С++, результирующий строковый объект в памяти намного ближе к 2kB.

Чтобы измерить память в Java, я использую Instrumentation. Для С++ я беру длину сериализованного объекта (например, строки).

4b9b3361

Ответ 1

Я думаю, что есть несколько факторов. Прежде всего, как сказал Брюс Мартин, объекты в java имеют накладные расходы по 16 байт на объект, С++ - нет. Во-вторых, строки в Java могут составлять 2 байта на символ вместо 1. В-третьих, может быть, что Java резервирует больше памяти для своих строк, чем С++ std::string.

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

Ответ 2

Предполагая, что ваш XML файл содержит в основном символы ASCII и использует кодировку, представляющую их как одиночные байты, вы можете оценить размер памяти как минимум вдвое, так как Java использует UTF-16 внутренне (я слышал о некоторые JVM, которые пытаются оптимизировать это, ты). В дополнение к этому будут накладные расходы на 2 объекта (экземпляр String и внутренний массив char) с некоторыми полями, IIRC - около 40 байтов в целом.

Таким образом, ваш "размер объекта" 33kb определенно неверен, если вы не используете странную JVM. Должны быть некоторые проблемы с методом, который вы используете для его измерения.

Ответ 3

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

Подробнее см. http://www.javamex.com/tutorials/memory/string_memory_usage.shtml.

Ответ 4

String: рост памяти String отслеживает его внутренний рост массива char. Тем не менее, класс String добавляет дополнительные 24 байта накладных расходов. Для непустой строки размером 10 символов или менее добавленные накладные расходы относительно полезной полезной нагрузки ( 2 байта для каждого char плюс 4 байта для длины) составляют от 100 до 400 процентов.

Подробнее: Каково потребление памяти объектом в Java?

Ответ 5

Да, вы должны GC и дать ему время для завершения. Просто System.gc(); и напечатать totalMem() в цикле. Вы также можете создать миллион строковых копий в массиве (размер пустого массива и затем заполнить строки), чтобы быть уверенным, что вы измеряете размер строк, а не другие объекты службы, которые могут присутствовать в вашей программе. Только одна строка не может принимать 32 кб. Но иерархичность объектов XML может быть.

Сказал, что я не могу противостоять иронии, что никто не заботится о памяти (и кеш-хитах) в мире Java. Мы знаем, что JIT улучшается, и в некоторых случаях он может превзойти собственный С++-код. Таким образом, нет необходимости беспокоиться об оптимизации памяти. Предварительная оптимизация - это корень всех зол.

Ответ 6

Как указано в других ответах, Java String добавляет накладные расходы. Если вам нужно сохранить большое количество строк в памяти, я предлагаю вам вместо них сохранить их в качестве байта []. При этом размер в памяти должен быть таким же, как размер на диске.

String → byte []:

String a = "hello";
byte[] aBytes = a.getBytes();

byte [] → String:

String b = new String(aBytes);