Проучване на JVM Tuning Flags

1. Общ преглед

Възможно е да настроите HotSpot JVM с различни настройки за настройка. Тъй като има стотици такива флагове, проследяването им и стойностите им по подразбиране може да бъде малко плашещо.

В този урок ще представим няколко начина за откриване на такива настройки за настройка и ще се научим как да работим с тях.

2. Общ преглед на Java Options

Командата 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.

Стойностите по подразбиране за някои флагове може да са различни на различните платформи, което е показано в последната колона. Например продуктът означава, че настройката по подразбиране на флага е еднаква за всички платформи; най Пд продуктови средствата че настройките по подразбиране на знамето е платформено-зависими. Най- управляеми стойности могат да се променят динамично по време на изпълнение.

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 :

[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 и също така научихме няколко трика за по-ефективна работа с тях.