Для простого "Hello World" нужна виртуальная память 10G на 64-битной машине против 1G на 32-битной?

Запустив простую Java-программу на нашей производственной машине, я заметил, что эта программа потребляет больше 10 ГБ. Я знаю, что виртуальная память не так важна, но, по крайней мере, я хотел бы понять, почему это необходимо.

public class Main {
  public static void main(String[] args) {
        System.out.println("Hello World!");
        try {
                Thread.sleep(10000);
        } catch(InterruptedException e) {
                /* ignored */
        }
  }
}

Вот что говорит top, когда я запускаю эту небольшую программу:

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
18764 myuser    20   0 10.2g  20m 8128 S  1.7  0.1   0:00.05 java

Кто-нибудь знает, почему это происходит?

uname -a говорит:

Linux m4fxhpsrm1dg 2.6.32-358.18.1.el6.x86_64 #1 SMP Fri Aug 2 17:04:38 EDT 2013 x86_64 x86_64 x86_64 GNU/Linux

На более старой машине с 32-битной линией одна и та же программа потребляет всего около 1 Гб. Старая машина имеет 4 ГБ оперативной памяти, новая 32 ГБ.

Ответ 1

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

Вы можете выбрать оба варианта с помощью -Xms и -Xmx параметров командной строки.

Ответ 2

Виртуальная память действительно не имеет значения для вас.

Основное различие между 32-битными и 64-битными - это то, что адресное пространство в 64-битном режиме невероятно велико. Если 10 GiB выглядит для вас много, обратите внимание, что .NET на 64-битной версии может использовать TiBs памяти, как это. Тем не менее, на 32-битной версии .NET гораздо более консервативен (и, следовательно, JVM) - адресное пространство составляет 4 гигабайта - это не так много.

Но это не имеет значения - это не имеет значения. Это просто упрощает программирование и не оказывает негативного влияния на ОС хоста. Он создает непрерывное адресное пространство для виртуальной машины, что означает, что вам не нужно фрагментировать кучу (или, что еще хуже, стек, где он более или менее невозможный), но они, как правило, являются только MiB или так), поскольку вам потребуется больше "реальной" памяти. Когда вы, наконец, совершаете виртуальную память, она становится немного более реальной - в этот момент ее более или менее нужно подкреплять некоторым хранилищем данных - будь то файл (своп) страницы или физическая оперативная память.

Дело в том, что физическое расположение памяти не обязательно непрерывное, но это делается вне вашей досягаемости, и отображение, как правило, очень быстро. С другой стороны, нужно, скажем, индексировать массив, который фактически фрагментирован на 10 различных блоков памяти виртуальных адресов, которые (совершенно ненужные) работают.

Итак, у вас это есть - виртуальная память почти свободна на 64-битной. Основной подход - "если он там, используйте его". Вы не ограничиваете другие приложения, и это экономит вам довольно много работы, если вы действительно используете его. Но до этого момента у вас есть только оговорка. Это вовсе не означает никакой физической памяти. Вы не платите за друзей, которые могли бы прийти сегодня вечером и сидеть за вашим столом, но у вас все еще есть место для них, чтобы сидеть, если они действительно приходят - и только когда они наконец придут, вы фактически получаете "заряженные".

См. этот вопрос для получения дополнительной информации о том, как ведет себя Java на разных машинах и в разных версиях: Каков максимальный размер кучи по умолчанию для JVM Sun от Java SE 6? Максимальный размер кучи также определяет объем зарезервированной виртуальной памяти, поскольку куча должна быть непрерывным адресным пространством. Если бы он не был предварительно зарезервирован, может случиться так, что куча не могла бы расширяться до этого максимального значения, потому что кто-то другой зарезервировал область адресного пространства в том месте, где куча должна расширяться.

Ответ 3

Это не ваша программа, использующая эту память, это Java VM, резервирующая эту память, независимо от того, какая программа загружена.

Ответ 4

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

Если приложение видит виртуальное адресное пространство размером 10 ГБ, все, что он сигнализирует приложению, заключается в том, что он может использовать адреса памяти до 10 ГБ, если захочет. Тем не менее, память фактически не выделяется в физической RAM до тех пор, пока она фактически не будет записана, и это делается на каждой странице, где страница представляет собой секцию памяти размером 4 КБ. Виртуальное адресное пространство - это просто виртуальное до фактического использования.

Скажем, приложению предоставляется 10 ГБ адресного пространства, и он начинает использовать некоторые из них. Вначале записывается "свежая" - ранее нетронутая страница этой виртуальной памяти, система на низком уровне "сопоставляет" эту виртуальную страницу с разделом физической памяти, а затем записывает ее. Но самому этому приложению не нужно беспокоиться о таких деталях, он просто действует так, как будто он имеет полный доступ к виртуальной области памяти.

В случае приложений Java это не само приложение, а Java, которому выделено это адресное пространство, а Java просто запрашивает огромное адресное пространство по умолчанию - запрашиваемая сумма вычисляется относительно размера физической памяти, но не потому что у него есть какая-то необходимость быть консервативной, но просто для практичности - приложение, вероятно, не захочет получить достаточный объем кучи, чтобы полностью довести сервер до колен, поэтому он работает, если предположить, что этого не произойдет. Как я уже говорил выше, это не означает, что это "выделено" или что системе пришлось потратить много ресурсов на это.

Ответ 5

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

Внутренний объект - основная память. Склад - это дисковое пространство.

Распределение виртуальной памяти на 10 ГБ для нового процесса не означает найти место для 10 миллиардов ящиков для нового клиента. Это означает печать 10 миллиардов ярлыков для ящиков со смежными идентификационными номерами на них.

Ответ 6

Это не объем физической памяти, которую приложение фактически использует. Виртуальная память, используемая всеми процессами, может на несколько порядков превышать объем физической памяти на машине без каких-либо очевидных проблем.

Ответ 7

Ваша программа НЕ использует столько памяти. JVM/OS резервирует эту память, т.е. Предел UPTO, который может использовать ваша программа. Кроме того, как ясно сказано в одном из ответов. 32 бит и 64 бит не имеют к этому никакого отношения. 32 бит означает, что вы можете получить доступ к ячейкам физической памяти до 2 ^ 32. и 64 бит означает до 2 ^ 64.