Понимание распределения памяти JVM и нехватка памяти Java: пространство кучи
Я смотрю в действительно понимание, как распределение памяти работает в JVM. Я пишу приложение, в котором я получаю Out of Memory: исключения Heap Space.
Я понимаю, что могу передать аргументы VM, такие как Xms и Xmx, чтобы увеличить пространство кучи, которое JVM выделяет для запущенного процесса. Это одно из возможных решений проблемы, или я могу проверить свой код на наличие утечек памяти и устранить проблему там.
Мои вопросы:
1) Как JVM фактически выделяет память для себя? Как это связано с тем, как ОС передает доступную память JVM? Или, в целом, как на самом деле работает распределение памяти для любого процесса?
2) Как виртуальная память вступает в игру? Допустим, у вас есть система с 32 ГБ физической памяти, и вы выделяете все 32 ГБ для своего процесса Java. Допустим, ваш процесс на самом деле потребляет все 32 ГБ памяти. Как мы можем заставить процесс использовать виртуальную память вместо того, чтобы работать с исключениями OOM?
Благодарю.
4 ответа
Как JVM фактически выделяет память для себя?
Для кучи выделяется одна большая конитная область памяти максимального размера. Первоначально это виртуальная память, однако со временем она становится реальной памятью для частей, которые используются под управлением ОС.
Как это связано с тем, как ОС передает доступную память JVM?
JVM не имеет представления о свободной памяти в ОС.
Или, в целом, как на самом деле работает распределение памяти для любого процесса?
В общем, он использует malloc и бесплатно.
Как виртуальная память вступает в игру?
Первоначально виртуальная память выделяется, и это превращается в реальную память, как используется. Это нормально для любого процесса.
Допустим, у вас есть система с 32 ГБ физической памяти, и вы выделяете все 32 ГБ для своего процесса Java.
Ты не можешь Операционная система нуждается в некоторой памяти, и будет память для других целей. Даже в JVM куча является лишь частью используемой памяти. Если у вас есть 32 ГБ памяти, я рекомендую как 24 ГБ кучи макс.
Допустим, ваш процесс на самом деле потребляет все 32 ГБ памяти,
Допустим, у вас есть 48 ГБ, и вы запускаете процесс, который использует 32 ГБ основной памяти.
Как мы можем заставить процесс использовать виртуальную память вместо того, чтобы работать с исключениями OOM?
Приложение использует виртуальную память с самого начала. Вы не можете сделать кучу слишком большой, потому что если она начнет заменять вашу машину (а не только ваше приложение), она станет непригодной для использования.
Тщательно вы можете использовать больше памяти, чем у вас физически, используя кучу памяти. Однако управляемая память должна быть в физической памяти, поэтому, если вам нужна куча 32 ГБ, купите 64 ГБ основной памяти.
JVM (или, если уж на то пошло, любой процесс), который хочет выделить память, будет вызывать функцию C malloc во время выполнения. Эта функция поддерживает кучную память среды выполнения C. Он, в свою очередь, получает память от ядра операционной системы - используемая для этого функция зависит от платформы; в Linux это могут быть системные вызовы brk или sbrk.
Как только память была получена JVM, она управляет самой памятью, выделяя ее части различным объектам, созданным работающей программой.
Виртуальная память полностью обрабатывается ядром операционной системы. Ядро управляет отображением страниц физической памяти в адресное пространство различных процессов; если физической памяти меньше, чем требуется всем процессам в системе, ядро ОС выгрузит часть ее на диск.
Вы не можете (и не должны) принуждать процессы использовать виртуальную память. Это прозрачно для вашего процесса.
Если вы получаете ошибки "Недостаточно памяти", причинами этого могут быть:
Пределы JVM превышены. Они управляются различными аргументами командной строки и / или свойствами, как вы указали в своем вопросе
В операционной системе могло не хватить места подкачки (или не было настроено места подкачки для запуска). Или некоторые ОС даже не поддерживают виртуальную память, и в этом случае у вас заканчивается реальная память.
Большинство ОС имеют возможности для администратора по ограничению объема памяти, потребляемой процессом - например, в Linux системный вызов setrlimit и / или команда оболочки ulimit, обе из которых устанавливают ограничения, которые будет соблюдать ядро. Если процесс запрашивает больше памяти, чем разрешено ограничениями, попытка завершится неудачно (обычно это приводит к сообщению о нехватке памяти).
JVM выделяет кучу памяти Java из ОС, а затем управляет кучей для приложения Java. Когда приложение создает новый объект, JVM выделяет непрерывную область памяти кучи для его хранения. Объект в куче, на который ссылается любой другой объект, является "живым" и остается в куче до тех пор, пока на него продолжают ссылаться. Объекты, на которые больше нет ссылок, являются мусором и могут быть удалены из кучи, чтобы освободить место, которое они занимают. JVM выполняет сборку мусора (GC) для удаления этих объектов, реорганизуя объекты, оставшиеся в куче.
Источник: http://pubs.vmware.com/vfabric52/index.jsp?topic=/com.vmware.vfabric.em4j.1.2/em4j/conf-heap-management.htmlВ системе, использующей виртуальную память, физическая память делится на страницы одинакового размера. Память, к которой обращается процесс, также делится на логические страницы одинакового размера. Когда процесс ссылается на адрес памяти, менеджер памяти извлекает с диска страницу, содержащую указанный адрес, и помещает ее на свободную физическую страницу в ОЗУ.
Источник: http://searchstorage.techtarget.com/definition/virtual-memory
В этом блоге рассматривается использование памяти Java, которое может оказаться полезным:
http://www.waratek.com/blog/november-2013/introduction-to-real-world-jvm-memory-utilisation