Конфигурация производительности Java-машины

Выбор java-машины

Для корректной работы приложения необходимо использовать Java Development's Kit (JDK) версии, указанной в разделе Условия эксплуатации. Выбор любой другой реализации Java или версии JDK не гарантирует стабильной работы приложения.

Основные концепции конфигурирования производительности

Конфигурирование производительности java-машины сводится к управлению ее памятью и Garbage collector (сборщиком мусора).

Объект содержится в памяти java-машины до тех пор, пока на него есть ссылки. Если на объект нет ссылок, он удаляется из памяти специальным процессом, запускаемым Garbage collector (сборщиком мусора) по определенному алгоритму. Запуск и работа этого процесса называется "сборка мусора".

Модель памяти java представлена несколькими разделами:

  • heap (куча) — хранятся объекты, создаваемые приложением.

    • young generation (молодое поколение) — попадают объекты при создании;
    • old generation (старое поколение) — перемещаются объекты, пережившие несколько сборок мусора.
  • metaspace — специальный раздел, в котором хранятся java-классы, методы и прочие объекты.

В heap периодически работает Garbage collector, который освобождает память под новые объекты.

Если Garbage collector не может освободить достаточно памяти для новых объектов (объектов, на которые есть ссылки, слишком много), то приложение завершает работу с ошибкой OutOfMemoryError. Эта же ошибка возникает, если в metaspace не хватит места для расположения новых объектов. Объем занимаемой памяти в metaspace не растет с увеличением нагрузки на приложение, поэтому достаточно один раз установить этому разделу памяти разумный предел.

Если Garbage collector еще может освобождать память, но освобождает ее в объеме, который быстро занимается новыми объектами, то наблюдается падение производительности приложения: частые, продолжительные зависания, связанные с тем, что при "сборке мусора" все рабочие потоки приложения останавливаются, и наблюдается высокая нагрузка на процессор сервера во время сборки мусора.

Исходя из вышеописанного следует выделять достаточно памяти для heap java.

Опции для конфигурирования работы java-машины

Конфигурирование производительности java-машины проводится с помощью java-опций запуска приложения.

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

Для ОС Linux опции перечисляются в файле setenv.sh в значении переменной CATALINA_OPTS.

CATALINA_OPTS="-server \

-Dfile.encoding=UTF-8 \

-Xms4096m \

-Xmx8192m"

Значения по умолчанию для java-опций и версию java-машины можно узнать, выполнив в консоли сервера команду:

java -XX:+PrintFlagsFinal -version

Ниже перечислены значимые для работы и мониторинга приложения java-опции.

Группа java-опций для работы и мониторинга приложения

  • -server — явно указывает использовать серверную версию виртуальной машины java (Java HotSpot Server VM). Эта версия специально оптимизирована для выполнения приложения на сервере.
  • -Xms — (InitialHeapSize) указывает, сколько памяти изначально будет выделено под кучу (heap) java-машины операционной системой. На production-серверах рекомендуется устанавливать значение параметра, равное значению -Xmx во избежание использования приложением swap.
  • -Xmx — (MaxHeapSize) указывает предел памяти, которая может быть выделена под кучу (heap) java-машины операционной системой.
  • -XX:MaxMetaspaceSize — указывает предел памяти, которая может быть выделена под Metaspace операционной системой.
  • -XX:ReservedCodeCacheSize — указывает предел памяти для кэша динамически скомпилированного кода Java. Обычно значения по умолчанию достаточно, однако, если возникают проблемы с производительностью, а используемый объем кэша подходит к пределу либо в логах Tomcat замечены предупреждения "VM warning: CodeCache is full. Compiler has been disabled", необходимо вручную поднять лимит.
  • -XX:-UseCompressedClassPointers — выключает сжатие указателей на классы, что экономит использование памяти Non Heap. При этом работающее сжатие указателей сэкономило бы меньше памяти из-за сравнительно небольшого объема Metaspace, используемого приложением.
  • -Xlog:gc: — в качестве значения указывается путь до лога сборок мусора java.

    Для ОС Linux чтобы лог не переписывался при перезапуске, а создавался новый, рекомендуем указать путь с датой и временем в названии лога, например, -Xlog:gc:/opt/naumen/nausd4/tomcat/logs/gc.log.$(date +%Y%m%d_%H%M):time.

Группа опций, обеспечивающих мониторинг работы приложения по JMX

Следующие опции позволяют производить мониторинг работы приложения в реальном времени с помощью технологии Java Management Extensions (JMX) с использованием утилит jconsole, jvisualvm. Необходимость такого подключения иногда возникает при локализации проблем в работе приложения:

  • -Dcom.sun.management.jmxremote.port=8999 — порт, по которому можно будет подключиться.
  • -Dcom.sun.management.jmxremote.authenticate=false — указывает, что можно будет подключиться к приложению без авторизации.

    Если для безопасности планируется назначить логин и пароль на подключение по jmx, следует воспользоваться инструкцией на сайте tomcat (ссылка на инструкцию).

  • -Dcom.sun.management.jmxremote.ssl=false

Группа опций для включения автоматического снимка памяти приложения при ошибке OutOfMemoryError

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

Опции для снимка памяти приложения рекомендуется включать только по просьбе специалистов компании NAUMEN.

  • -XX:+HeapDumpOnOutOfMemoryError — включает автоматический снимок памяти приложения при ошибке "OutOfMemoryError".
  • -XX:HeapDumpPath=/opt/naumen/nausd4/ — указывает путь, по которому будет создан файл со снимком кучи (heapDump).