Автор оригинала: Ali Dehghani.
1. Обзор
Можно настроить JVM HotSpot с помощью различных флагов настройки. Поскольку таких флагов сотни, отслеживать их и их значения по умолчанию может быть немного сложно.
В этом уроке мы представим несколько способов обнаружения таких флагов настройки и научимся работать с ними.
2. Обзор опций Java
Команда java поддерживает широкий спектр флагов, относящихся к следующим категориям:
- Стандартные опции, которые гарантированно поддерживаются всеми реализациями JVM. Обычно эти параметры используются для повседневных действий, таких как –classpath, -cp, –version, и так далее
- Дополнительные параметры, которые не поддерживаются всеми реализациями JVM и обычно могут быть изменены. Эти параметры начинаются с -X
Пожалуйста, обратите внимание, что мы не должны использовать эти дополнительные опции небрежно. Кроме того, некоторые из этих дополнительных опций являются более продвинутыми и начинаются с -XX .
В этой статье мы сосредоточимся на более продвинутых флагах -XX .
3. Флаги настройки JVM
Чтобы перечислить глобальные флаги настройки JVM, мы можем включить PrintFlagsFinal флаг следующим образом:
>> java -XX:+PrintFlagsFinal -version [Global flags] uintx CodeCacheExpansionSize = 65536 {pd product} {default} bool CompactStrings = true {pd product} {default} bool DoEscapeAnalysis = true {C2 product} {default} double G1ConcMarkStepDurationMillis = 10.000000 {product} {default} size_t G1HeapRegionSize = 1048576 {product} {ergonomic} uintx MaxHeapFreeRatio = 70 {manageable} {default} // truncated openjdk version "14" 2020-03-17 OpenJDK Runtime Environment (build 14+36-1461) OpenJDK 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)
Как показано выше, некоторые флаги имеют значения по умолчанию для этой конкретной версии JVM.
Значения по умолчанию для некоторых флагов могут отличаться на разных платформах, что показано в последнем столбце. Например, product означает, что настройка флага по умолчанию одинакова для всех платформ; pd product означает, что настройка флага по умолчанию зависит от платформы. Значения управляемые могут динамически изменяться во время выполнения.
3.1. Диагностические флаги
Флаг PrintFlagsFinal , однако, не показывает все возможные флаги настройки. Например, чтобы также увидеть флаги настройки диагностики, мы должны добавить флаг UnlockDiagnosticVMOptions :
>> java -XX:+PrintFlagsFinal -version | wc -l 557 >> java -XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions -version | wc -l 728
Очевидно, что есть еще пара сотен флагов, когда мы включаем диагностические опции. Например, печать статистики отслеживания собственной памяти доступна только как часть диагностических флагов:
bool PrintNMTStatistics = false {diagnostic} {default}
3.2. Экспериментальные флаги
Чтобы также увидеть экспериментальные варианты, мы должны добавить UnlockExperimentalVMOptions флаг:
>> java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version | wc -l 809
3.3. Флаги JVMCI
Начиная с Java 9, интерфейс компилятора JVM или JVMCI позволяет нам использовать компилятор, написанный на Java, такой как Graal, в качестве динамического компилятора.
Чтобы увидеть параметры, связанные с JVMCI, мы должны добавить еще несколько флагов, а также даже включить JVMCI:
>> java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions \ >> -XX:+JVMCIPrintProperties -XX:+EnableJVMCI -XX:+PrintFlagsFinal -version | wc -l 1516
Однако в большинстве случаев использования глобальных, диагностических и экспериментальных вариантов должно быть достаточно, и это поможет нам найти флаг, который мы имеем в виду.
3.4. Собрать Все Это Воедино
Эти комбинации опций могут помочь нам найти флаг настройки, особенно когда мы не помним точного названия. Например, чтобы найти флаг настройки, связанный с мягкими ссылками в Java:
>> alias jflags="java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version" >> jflags | grep Soft size_t SoftMaxHeapSize = 4294967296 {manageable} {ergonomic} intx SoftRefLRUPolicyMSPerMB = 1000 {product} {default}
Из результата мы можем легко догадаться, что SoftRefLRUPolicyMSPerMB – это флаг, который мы ищем.
4. Различные типы флагов
В предыдущем разделе мы затронули важную тему: типы флагов. Давайте еще раз взглянем на java -XX:+PrintFlagsFinal -version output:
[Global flags] uintx CodeCacheExpansionSize = 65536 {pd product} {default} bool CompactStrings = true {pd product} {default} bool DoEscapeAnalysis = true {C2 product} {default} double G1ConcMarkStepDurationMillis = 10.000000 {product} {default} size_t G1HeapRegionSize = 1048576 {product} {ergonomic} uintx MaxHeapFreeRatio = 70 {manageable} {default} // truncated
Как показано выше, каждый флаг имеет определенный тип.
Логические параметры используются для включения или отключения функции . Такие параметры не требуют значения. Чтобы включить их, нам просто нужно поставить знак плюс перед именем опции:
-XX:+PrintFlagsFinal
Напротив, чтобы отключить их, мы должны добавить знак минус перед их именем:
-XX:-RestrictContended
Другим типам флагов требуется значение аргумента. Можно отделить значение от имени параметра пробелом, двоеточием, знаком равенства, или аргумент может непосредственно следовать за именем параметра (точный синтаксис отличается для каждого параметра):
-XX:ObjectAlignmentInBytes=16 -Xms5g -Xlog:gc
5. Документация и исходный код
Найти правильное название флага-это одно. Найти, что делает этот конкретный флаг под капотом, – это совсем другая история.
Один из способов узнать такие подробности-это ознакомиться с документацией. Например, документация для команды java в разделе спецификации инструментов JDK – отличное место для начала.
Иногда никакое количество документации не может превзойти исходный код. Поэтому, если у нас есть имя конкретного флага, мы можем изучить исходный код JVM, чтобы выяснить, что происходит.
Например, мы можем проверить исходный код Hotspot Jvm из GitHub или даже их репозитория Mercurial , а затем:
>> git clone [email protected]:openjdk/jdk14u.git openjdk >> cd openjdk/src/hotspot >> grep -FR 'PrintFlagsFinal' . ./share/runtime/globals.hpp: product(bool, PrintFlagsFinal, false, ./share/runtime/init.cpp: if (PrintFlagsFinal || PrintFlagsRanges) {
Здесь мы ищем все файлы, содержащие строку PrintFlagsFinal . Найдя ответственные файлы, мы можем оглядеться и посмотреть, как работает этот конкретный флаг.
6. Заключение
В этой статье мы увидели, как мы можем найти почти все доступные флаги настройки JVM, а также узнали несколько трюков, чтобы работать с ними более эффективно.