2010-01-21 4 views
33

Это isnotpossible, чтобы увеличить максимальный размер кучи Java после запуска виртуальной машины. Каковы технические причины этого? Могут ли алгоритмы сбора мусора зависеть от наличия фиксированного объема памяти? Или это из соображений безопасности, чтобы запретить Java-приложение из DOS'и других приложений в систему, потребляя всю доступную память?Почему максимальный размер кучи Java исправлен?

+0

Аналогичный вопрос: «Почему JVM (Sun) имеет фиксированный верхний предел для использования памяти (-Xmx)?» - http://stackoverflow.com/questions/3358328/why-does-the-sun-jvm-have-a-fixed-upper-limit-for-memory-usage-xmx – sleske

ответ

23

В JVM Sun, который, как я знал ранее, вся куча должна быть выделена в смежном адресном пространстве. Я полагаю, что для больших значений кучи, довольно сложно добавить в адресное пространство после запуска, при этом он остается смежным. Вы, вероятно, должны получить его при запуске, или совсем нет. Таким образом, он фиксирован.

Даже если он не используется сразу, адресное пространство для всей кучи зарезервировано при запуске. Если он не может зарезервировать достаточно большой непрерывный блок адресного пространства для значения -Xmx, которое вы передадите, он не запустится. Вот почему трудно выделить куски 1,4 ГБ на 32-битной Windows - потому что трудно найти смежное адресное пространство такого размера или больше, так как некоторые библиотеки DLL любят загружать в определенных местах, фрагментируя адресное пространство. На самом деле это не проблема, когда вы идете на 64-разрядную версию, так как есть гораздо больше адресного пространства.

Это почти наверняка по соображениям производительности. Я не мог найти потрясающую ссылку, подробно описывающую это, но вот довольно хорошая цитата от Питера Кесслера (full link - обязательно прочитайте комментарии), которые я нашел при поиске. Я считаю, что он работает на JVM на Солнце.

Причина нужна смежная память область для кучи является то, что у нас есть кучи структур данных на сторону, которые проиндексированных (масштабируемый) смещение от начала кучи. Например, мы сообщим справками об объектах отслеживания объектов с массивом «маркерных меток» , который имеет один байт для каждого 512 байтов кучи.Когда мы храним ссылку в куче, у нас есть , чтобы отметить соответствующий байт в массиве маркеров . Мы правильно переместим адрес назначения магазина и , чтобы проиндексировать массив маркеров. Увлекательные арифметические игры для азартных игр, которые вы не можете сделать на Java, которые вы получаете (есть , чтобы :-) играть на C++.

Это было в 2004 году. Я не уверен, что изменилось с тех пор, но я уверен, что он все еще держится. Если вы используете такой инструмент, как Process Explorer, вы можете видеть, что виртуальный размер (добавить столбцы памяти виртуального размера и частного размера) приложения Java включает в себя полный размер кучи (плюс другое необходимое пространство, без сомнения), начиная с момента запуска , хотя память «используется» в процессе не будет там, где до тех пор, пока куча не начнет заполняться ...

4

Я думаю, что короткий, пристойный ответ - это потому, что Солнце не нашло того, что стоит времени и затрат на разработку.

Самый неотразимый прецедент для такой функции на рабочем столе, IMO и Java всегда был катастрофой на рабочем столе, когда дело доходит до механики запуска JVM. Я подозреваю, что те, кто больше всего думают об этих проблемах, имеют тенденцию сосредотачиваться на стороне сервера и просматривать любые другие данные, которые лучше всего оставляют для родных оболочек. Это неудачное решение, но оно должно быть одним из решающих пунктов при принятии решения о правильной платформе для приложения.

+0

Если вы можете расти, очень разумный запрос также может сокращаться, а Sun JVM действительно не любит отказываться от памяти. Microsoft JVM может использовать всю память в системе. –

+0

@ Thorbjørn Ravn Andersen, он может сжиматься, хотя это несколько недавняя и плохо документированная способность (а также что-то действительно отвратительное на рабочем столе, которое отсутствовало). См. -XX: MaxHeapFreeRatio и -XX: MinHeapFreeRatio http://stackoverflow.com/questions/763295/setting-jvm-heap-size-at-runtime/763305#763305 – Yishai

+0

Недокументированные XX-опции не учитываются :) –

3

У меня возникает ощущение, что это связано с управлением памятью в отношении других приложений, работающих в операционной системе.

Если вы установили максимальный размер кучи, например, объем ОЗУ на коробке, вы позволите виртуальной машине решить, сколько памяти она требует (до этого предела). Проблема заключается в том, что виртуальная машина может эффективно калечить машину, на которой она запущена, потому что она возьмет на себя всю память на коробке, прежде чем она решит, что ей нужно собрать мусор.

Когда вы указываете максимальный размер кучи, то, что вы говорите виртуальной машине, вы можете использовать этот объем памяти, прежде чем вам нужно начать сбор мусора. У вас не может быть больше, потому что если вы возьмете больше, то другие приложения, запущенные на ящике, замедлятся, и вы начнете замену на диск, если будете использовать больше этого.

Также имейте в виду, что они представляют собой два значения относительно памяти, то есть «текущий размер кучи» и «максимальный размер кучи». Текущий размер кучи - это объем памяти, который в настоящее время использует размер кучи, и, если он требует больше, он может изменять размер кучи, но он не может изменять размер кучи выше значения максимального размера кучи.

+0

Я думаю, что это прекрасный ответ на сервере, где есть администратор который понимает, как настроить JVM (или, по крайней мере, вы можете это обоснованно ожидать), и устанавливает соответствующие максимумы, чтобы хорошо работать с другими процессами. Тем не менее, на рабочем столе вы просите пользователя пойти возиться с файлами конфигурации и сценариями запуска, с которыми у них нет опыта или понимания, а текущий ответ Sun - написать пусковую установку в C. – Yishai

+0

@Yishai: значения по умолчанию для VM к значениям, которые вполне приемлемы для большинства приложений, и iirc значения по умолчанию также настраиваются относительно доступной ОЗУ. Для приложений, в которых проблема по умолчанию является проблемой, сценарий установки может легко создать сценарий запуска (а не пусковую установку), которая устанавливает еще один макс. Edit: И кстати, мне это тоже не нравится, и я уверен, что Sun может удалить эту вещь, если захочет. – Fredrik

+0

@Fredrik, что, если пользователь добавит барабан в свою систему после запуска скрипта установки? Некоторые настольные приложения хотят использовать больше доступной ОЗУ, если они доступны (например, для кэширования). – Yishai

2

От компании IBM performance tuning tips (поэтому не могут быть непосредственно применимы к виртуальным машинам Солнца)

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

JVM имеет пороговые значения, которые он использует для управления хранилищем JVM. Когда достигнуты пороговые значения, сборщик мусора вызывается для освобождения неиспользуемого хранилища. Поэтому сбор мусора может привести к значительному ухудшению производительности Java. Перед изменением размера начальной и максимальной кучи, вы должны рассмотреть следующую информацию: В большинстве случаев вы должны установить максимальный размер кучи JVM на значение выше начального размера кучи JVM. Это позволяет JVM эффективно работать в нормальные периоды устойчивого состояния в пределах начальной кучи, а также эффективно работать в периоды высокого объема транзакций, расширяя кучу до максимального размера кучи JVM. В некоторых редких случаях, когда требуется абсолютная оптимальная производительность, вы можете указать одно и то же значение как для начального, так и для максимального размера кучи. Это устранит некоторые накладные расходы, которые возникают, когда JVM необходимо расширять или сокращать размер кучи JVM. Убедитесь, что область достаточно большая, чтобы удерживать указанную кучу JVM. Остерегайтесь слишком большого размера начальной кучи.В то время как большой размер кучи изначально улучшает производительность, задерживая сбор мусора, большой размер кучи в конечном итоге влияет на время отклика, когда сбор мусора в конечном итоге вызывается, потому что процесс сбора занимает больше времени.

Итак, я думаю, причина, по которой вы не можете изменить значение во время выполнения, состоит в том, что это может не помочь: либо у вас достаточно места в вашей куче, либо нет. Как только вы закончите, будет запущен цикл GC. Если это не освобождает пространство, вы все равно набиты. Вам нужно поймать OutOfMemoryException, увеличить размер кучи, а затем повторить вычисления, надеясь, что на этот раз у вас будет достаточно памяти.

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

Я признаю, что все немного неудовлетворительно, и кажется немного ленивым, так как я могу представить разумную стратегию сбора мусора, которая увеличит размер кучи, когда GC не сможет освободить достаточно места. Является ли мое воображение воплощением реализации GC с высокой производительностью, является другим вопросом:)

8

Исторически сложилось так, что это ограничение было причиной, которая не позволяла апплетам в браузере потреблять всю память пользователей. Виртуальная машина Microsoft, которая никогда не имела такого ограничения, фактически позволяла это делать, что могло привести к какой-то атаке «Отказ в обслуживании» против компьютера пользователя. Только год назад Sun представила версию 1.6.0 Update 10 VM, чтобы позволить апплетам указать, сколько памяти они хотят (ограничено определенной фиксированной долей физической памяти), а не всегда ограничивать их до 64 МБ даже на компьютерах которые имеют 8 ГБ или более.

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

+1

Вы правы, есть сообщения об ошибках с просьбой об этом: http://bugs.sun.com/view_bug.do?bug_id=4741914, http://bugs.sun.com/view_bug.do?bug_id=4408373 –

+0

+1 Это единственный ответ, который имеет для меня смысл, в том числе связанные с вопросами. Просто проводите часы, преследуя проблему с Crashplan, где простое исправление заключается в том, чтобы просто вызвать неясный параметр в файле с неясными настройками. Кто на земле выбирает верхний предел 256 МБ, позволяя моей резервной копии сбой, не замечая в течение нескольких недель и имея избыточную системную память, чтобы сэкономить. –

Смежные вопросы