Назад | Перейти на главную страницу

Память Java ограничена, но по-прежнему используется слишком много оперативной памяти

Я много читал, но то, что я читал до сих пор, не имело особого смысла, поэтому я задаю здесь новый вопрос о Java и памяти.

Итак, я запускаю приложение Java со следующими аргументами CLI

-Xms48m
-Xmx96m
-XX:MetaspaceSize=80m
-XX:MaxMetaspaceSize=150m

В моем приложении у меня есть такой код для отображения используемой памяти:

Runtime runtime = Runtime.getRuntime();
//Used mem: runtime.totalMemory() - runtime.freeMemory()
//Total mem: runtime.totalMemory()
//Max mem: runtime.maxMemory()

Результаты ожидаются:

Used Memory: 43 mb
Free Memory: 16 mb
Total Memory: 60 mb
Max Memory: 96 mb

У меня также был запущен сборщик мусора, я сделал дамп кучи и проанализировал его, и он также говорит, что используется около 43 МБ.

Так что эта часть пока в порядке. Но теперь, если я запустил htop в Linux, я получаю эти числа для своего Java-приложения:

RES: 409M
DATA: 611M

Первый вопрос:

  1. Почему это так много?
  2. Если я перезапускаю свое приложение, оно начинается с RES: 224M, DATA: 339M и растет и растет до тех пор, пока через день не достигнет 409M / 611M, как упоминалось выше, а затем я перезапускаю приложение с помощью задания cron, иначе моя оперативная память исчезнет . Как я могу это предотвратить?

(У меня 80 экземпляров одного и того же приложения, запущенного на сервере с 32 ГБ ОЗУ).

Вот скриншот ситуации:

Платформа:

При анализе использования памяти Java вы забыли размер памяти, используемой DirectBufferс. Вы можете контролировать это с помощью -XX:MaxDirectMemorySize и по умолчанию используется максимальный размер кучи.

В худшем случае вы позволяете Java использовать 342 МБ памяти для своих данных и некоторых других второстепенных зон памяти. Описание всех зон памяти можно найти на Baeldung.

Когда вы начинаете анализировать реальное потребление памяти, вам нужно учитывать также размер библиотек Java, который не велик, но jvm.so составляет около 20 МБ. Все это составляет RSS цифры, которые вы привели.

Однако, если вы хотите проверить, может ли ваша система поддерживать такое количество JVM, в игру вступают тонкости памяти Linux:

  1. RSS учитывает все страницы, находящиеся в памяти, независимо от того, используются ли они для личных данных JVM или кэшированных частей файлов и библиотек. Подобно тому, как работает сборщик мусора в Java, ядро ​​Linux освобождает кеши файлов, когда у него не хватает физической памяти. Более того, многие страницы могут быть разделены между JVM
  2. DATA измеряет всю личную память mmap-ed в виртуальное пространство процессов. Большинство из них никогда не будет иметь никакой физической памяти.

Если вы хотите подробно проверить виртуальную память каждой JVM, используйте:

pmap -p <processes_pid> -x

или отсортированная версия на грязных страницах:

pmap -p <processes_pid> -x | sort -rnk 4

и вы можете увидеть, что способствует этим RSS и DATA цифры.

редактировать: Вы можете узнать больше о том, как Linux классифицирует память и цифры, предоставленные многими инструментами на этот сайт