Картина тысячи забот, память jvm еще никогда не была такой простой!

Java JVM

Оригинал: Miss Sister Taste (идентификатор публичной учетной записи WeChat: xjjdog), добро пожаловать, пожалуйста, сохраните источник для перепечатки.

Студенты, которые видят эту картинку, не распространяют ее повсюду. Мы ограничим наше обсуждение небольшой областью, потому что эта картина очень мощная и я рисовал ее 10 лет!

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

Так какая польза от этой картинки? При устранении неполадок с памятью нам необходимо понять, в какой части возникла проблема. Если вы не сможете найти нужное место, то врезаться точно будет сложнее, и это отнимет у вас много сил.

Машина 4 ГБ, обычно используемаяXmxназначен наJVMДа, конечно, не слишком. Например3.5GBкакой-то тип. Это слишком жадно и может легко привести к аварийному завершению работы JVM. Почему это?

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

JVM — это наш основной корпус, так что поместите его на место героя. Таким образом, всю память можно разделить наJVM内存,操作系统物理内存,SWAPтри части.

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

В это время Linux запуститсяoom-killer, убейте процесс, который занимает больше всего памяти, в это время существует высокая вероятность того, что это ваш любимый процесс-ребенок JVM.

oom здесь относится к операционной системе, а не к JVM. Итак, вы найдете:Ваш Java-процесс умирает, но ничего не остается. Прошло так тихо.

Эту информацию можно получить только черезdmesgНайдена команда, относящаяся к категории операционной системы.

Итак, далее давайте взглянем на самую важную картинку, а затем объясним, что делают эти десятки частей.

Мы по-прежнему разделяем память на указанные выше три части, но делаем более детальное разделение памяти процесса JVM.

Прежде всего, для памяти JVM есть память в куче и память вне кучи.

Что касается памяти в куче, то это то место, с которым мы обычно имеем дело больше всего, потому что большинство наших объектов Java размещается в куче. При возникновении проблемы с переполнением используйтеjmap + matПосле ряда ожесточенных операций вы сможете легко и быстро найти проблемы.

Это навык, которым может овладеть эксперт по Java.

Ключ — это часть памяти вне кучи, что очень болезненно. Из-за того, что здесь много всего разного, легко запутаться.

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

Результат выполнения этого кода на самом деле неправильный, здесьunsafe, а не прямая память.

Итак, давайте посмотрим, что там внутри.

Во-первых, метапространство

Metaspace был добавлен после jdk8, чтобы заменить исходное постоянное поколение. То есть методический участок в исходном пермском районе (постоянная генерация) тоже здесь. Как видно из его первоначального названия, постоянные относятся к тем данным, которые мало изменяются, а главное — стабильность. Например, файлы классов, которые мы загружаем при запуске jvm, и прокси-классы, которые динамически генерируются во время выполнения.

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

Во-вторых, CodeCache

Во многих статьях очень мало введения в часть, но на самом деле это тоже очень важная область, не относящаяся к куче. так какJITдаJVMОчень важной особенностью, которую хранит CodeCahe, является двоичный код, сгенерированный компилятором «точно в срок». Разумеется, код JNI также размещен здесь.

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

локальная память

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

(1) Сетевая память

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

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

(2) Память нити

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

Это тоже область памяти, которая суммируется, но обычно не вызывает проблем.

(3) память JNI

Как упоминалось выше, код JNI, хранящийся в CodeCache, память JNI относится к конкретной памяти malloc этой части кода.

Например, zip-библиотека Java не завершается в куче JVM, но открывает для операций буферный пул вне кучи.

(4) Прямая память

Прямая память относится к памяти, которая использует API прямой памяти Java для работы. Эта часть памяти может управляться JVM, как это делает класс ByteBuffer.

Нижний слой ByteBuffer небезопасен, но unsafe не контролируется прямой памятью, это не одно и то же.

Прямое использование небезопасных программ из вышеупомянутых книг не вызовет прямого переполнения памяти JVM, но вызовет переполнение памяти операционной системы.


Итак, как мы видим эти воспоминания?

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

Сделав еще один шаг, используя функцию pmap, вы можете наблюдать за конкретным распределением памяти. Но не бойтесь, есть много общей памяти.

Для этого конкретного процесса вы можете обратиться к статье об устранении неполадок с памятью вне кучи, написанной ранее.

Если вы понимаете эти разделения памяти на графике, вам будет легко понять, почему инструмент NMT не может отображать статистику памяти JNI.

Далее давайте суммируем эти области памяти и какие параметры могут ими управлять.

  • куча-Xmx -Xms
  • метапространство-XX:MaxMetaspaceSize -XX:MetaspaceSize
  • куча-Xss
  • прямая память-XX:MaxDirectMemorySize
  • Хранение кода после JIT-компиляции-XX:ReservedCodeCacheSize
  • Другая память вне кучи не может контролироваться! Позволь этому произойти.

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

Как правило, мы используем2/3Поскольку куча пространства, это более разумно. Это ценность опыта. Например, 6 ГБ памяти, которые вы выделяете для JVM, лучше всего не превышать 4 ГБ.

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

Но мы должны смотреть на проблему с диалектическим мышлением. Для низкой частоты, когда большая зависимость от объема памяти, SWAP надо не только включать, но и включать побольше.

Об авторе:Мисс сестра вкус(xjjdog), публичная учетная запись, которая не позволяет программистам идти в обход. Сосредоточьтесь на инфраструктуре и Linux. Десять лет архитектуры, десятки миллиардов ежедневного трафика, обсуждение с вами мира высокой параллелизма, дающие вам другой вкус. Мой личный WeChat xjjdog0, добро пожаловать в друзья для дальнейшего общения.​