Java 32bit Xmx vs java 64bit Xmx

Я действительно смущен этим.

Xmx в соответствии с java-документами, является максимально допустимым размером кучи.
Xms - минимально необходимый размер кучи java и выделяется при запуске JVM.

На 32-битном JVM (4GB RAM), java -Xmx1536M HelloWorld дает возможность не выделять достаточную ошибку памяти.
На 64-битной JVM (4GB Ram), java -Xmx20G HelloWorld работает отлично. Но у меня даже не так много виртуальной или физической памяти.

Поэтому из этого я пришел к выводу, что Java 32 бит выделяет 1536M при запуске JVM, но Java 64 бит - нет.

Зачем? Для простого Hello World не требуется 1536M для запуска. Я просто указываю, что 1536M является максимальным, а не тем, что он необходим.

Объяснения кому-нибудь?

Ответы

Ответ 1

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

Если распределение не выполняется, тогда Java не запустится... как вы видели. Он не обязательно использует столько памяти, но выделяет необходимое адресное пространство вверх. Поскольку вы проходите -Xmx1536m, он говорит "хорошо", мне нужно выделить это, если вам это нужно... и поскольку он должен быть смежным, он делает это заранее, чтобы он мог гарантировать его (или не удалось выполнить попытку).

Такое поведение одинаково для 32-разрядных и 64-разрядных JVM. То, что вы видите, - это ограничение на 2 Гбайт адресного пространства для 32-битных процессов (по крайней мере, в Windows это ограничение - оно может быть немного больше на других платформах), что приводит к сбою этого распределения в 32-битном режиме, где 64 -bit не имеет проблем, поскольку имеет гораздо большее адресное пространство. Но, вы говорите, 1536 м меньше 2 ГБ, я должен быть хорошим, не так ли? Не совсем - куча - это не единственное, что выделяется в адресном пространстве, DLL и другие вещи также выделяются в адресном пространстве... поэтому получение смежного 1536-метрового фрагмента из 2 ГБ макс на 32-битном, к сожалению, очень маловероятно. Я видел значения ниже 1000 м сбой при 32-битных процессах с особенно плохой фрагментацией, и обычно 1200-1300 м - максимальная куча, которую вы можете указать на 32-битной.

В современных ОС, ASLR (рандомизация макета адресного пространства) делает фрагментацию 32-битного адресного пространства процесса хуже. Он намеренно загружает DLL файлы в случайные адреса по соображениям безопасности... делая его еще менее вероятным, вы можете получить большую смежную кучу в 32-разрядной версии.

В 64-битном пространстве адресное пространство настолько велико, что фрагментация уже не проблема, и огромные кучи могут быть выделены без проблем. Тем не менее, даже если у вас 4 ГБ ОЗУ на 32-битной памяти, ограничение на 2 ГБ на каждое адресное пространство для процесса (по крайней мере, в Windows) обычно означает, что максимальная куча обычно составляет всего 1300 м.

Ответ 2

На самом деле приложение не выделяет память Xmx при запуске.

Параметр -Xms настраивает загрузочную память. (Каковы параметры Xms и Xmx при запуске JVM?)

64-разрядная среда позволяет более крупное распределение памяти, а затем 32 бита. Но на самом деле он использует пространство HD, а не память.

Смотрите это другое сообщение для получения дополнительной информации.

Оценка максимального безопасного размера JVM-кучи в 64-битной Java

Ответ 3

В Windows существует различие в операциях выделения памяти с собственными низкоуровневыми функциями WinAPI, такими как VirtualAlloc.

"Резервное копирование" означает выделение непрерывной области в пространстве адресов процесса без фактического использования этой области виртуальной памяти. Выделенная область не подкрепляется фактическим физическим ОЗУ или местом подкачки и не потребляет свободной памяти. Любое приложение может резервировать любое количество адресного пространства, ограниченное только возможностью адресации памяти процессора (битностью).

"Committing" означает поддержку некоторой ранее сохраненной памяти с реальной памятью - ОЗУ или пространства подкачки, что делает его действительно доступным для чтения/записываемым процессом. Эта память берется из пула виртуальной памяти операционной системы (RAM и swap).

Альтернативой "фиксации" памяти (взяв пустую страницу из пула) является "отображение" файла в ранее "зарезервированную" память. Это не потребляет память из пула подкачки, а использует сопоставленный файл так же, как выделенное пространство подкачки для этой конкретной области адресного пространства процесса.

Собственные приложения Windows (например, JVM) резервируют память для всех кучек, необходимых в будущем, но фиксируют ее только по мере необходимости. Высокоуровневые операции с памятью, такие как функции стиля malloc() или "новые" операторы, действительно "совершают" по необходимости или даже выполняют собственный режим управления логикой кучи в режиме памяти с памятью, выполняемой впереди большими кусками, так как это ядро ​​с интенсивностью процессора вызывать и работать с детализацией страницы (4k).

В процессе запуска JVM "резервирует" память -Xmx, но "фиксирует" только -Xms. Оставшаяся зарезервированная память фиксируется по требованию, когда кучи растут. Таким образом, кучи могут вырасти до доступной памяти или параметра -Xmx, в зависимости от того, что меньше.