Java >> Java tutorial >  >> JVM

Find GC-algoritmen, der bruges af en JVM-instans

1. Oversigt

Ud over typiske udviklingsværktøjer såsom compiler og runtime, leveres hver JDK-udgivelse med et utal af andre værktøjer. Nogle af disse værktøjer kan hjælpe os med at få værdifuld indsigt i vores kørende applikationer.

I denne artikel skal vi se, hvordan vi kan bruge sådanne værktøjer til at finde ud af mere om GC-algoritmen, der bruges af en bestemt JVM-instans.

2. Eksempel på applikation

Igennem denne artikel vil vi bruge et meget simpelt program:

public class App {
    public static void main(String[] args) throws IOException {
        System.out.println("Waiting for stdin");
        int read = System.in.read();
        System.out.println("I'm done: " + read);
    }
}

Det er klart, at denne app venter og fortsætter med at køre, indtil den modtager noget fra standardinputtet. Denne suspension hjælper os med at efterligne opførselen af ​​langvarige JVM-applikationer.

For at bruge denne app skal vi kompilere App.java  fil med javac  og kør det derefter ved hjælp af java  værktøj.

3. Sådan finder du JVM-processen

For at finde den GC, der bruges af en JVM-proces, skal vi først identificere proces-id'et for den pågældende JVM-instans. Lad os sige, at vi kørte vores app med følgende kommando:

>> java App
Waiting for stdin

Hvis vi har JDK installeret, er den bedste måde at finde proces-id'et for JVM-instanser på at bruge jps værktøj. For eksempel:

>> jps -l
69569 
48347 App
48351 jdk.jcmd/sun.tools.jps.Jps

Som vist ovenfor kører der tre JVM-instanser på systemet. Det er klart, at beskrivelsen af ​​den anden JVM-instans ("App") matcher vores applikationsnavn. Derfor er proces-id'et, vi leder efter, 48347.

Ud over jps , kan vi altid bruge andre generelle hjælpeprogrammer til at bortfiltrere kørende processer. For eksempel den berømte ps  værktøj fra procps-pakken vil også fungere:

>> ps -ef | grep java
502 48347 36213   0  1:28AM ttys037    0:00.28 java App

Men jps  er meget nemmere at bruge og kræver mindre filtrering.

4. Brugte GC

Nu hvor vi ved, hvordan man finder proces-id'et, lad os finde GC-algoritmen, der bruges af JVM-applikationer, der allerede kører.

4.1. Java 8 og tidligere

Hvis vi er på Java 8, kan vi bruge jmap  værktøj til at udskrive heap-resuméet, heap-histogrammet eller endda generere et heap-dump . For at finde GC-algoritmen kan vi bruge -heapen  mulighed som:

>> jmap -heap <pid>

Så i vores særlige tilfælde bruger vi CMS GC:

>> jmap -heap 48347 | grep GC
Concurrent Mark-Sweep GC

For andre GC-algoritmer er outputtet næsten det samme:

>> jmap -heap 48347 | grep GC
Parallel GC with 8 thread(s)

4.2. Java 9+:jhsdb jmap

Fra og med Java 9 kan vi bruge jhsdb jmap  kombination for at udskrive nogle oplysninger om JVM-bunken. Mere specifikt ville denne særlige kommando svare til den forrige:

>> jhsdb jmap --heap --pid <pid>

For eksempel kører vores app med G1GC nu:

>> jhsdb jmap --heap --pid 48347 | grep GC
Garbage-First (G1) GC with 8 thread(s)

4.3. Java 9+: jcmd

I moderne JVM'er er jcmd  kommandoen er ret alsidig. For eksempel kan vi bruge det til at få nogle generelle oplysninger om heapen :

>> jcmd <pid> VM.info

Så hvis vi sender vores apps proces-id, kan vi se, at denne JVM-instans bruger Serial GC:

>> jcmd 48347 VM.info | grep gc
# Java VM: OpenJDK 64-Bit Server VM (15+36-1562, mixed mode, sharing, tiered, compressed oops, serial gc, bsd-amd64)
// omitted

Outputtet er det samme for G1 eller ZGC:

// ZGC
# Java VM: OpenJDK 64-Bit Server VM (15+36-1562, mixed mode, sharing, tiered, z gc, bsd-amd64)
// G1GC
# Java VM: OpenJDK 64-Bit Server VM (15+36-1562, mixed mode, sharing, tiered, compressed oops, g1 gc, bsd-amd64)

Med en lille smule grep magi, vi kan også fjerne alle disse lyde og bare få GC-navnet:

>> jcmd 48347 VM.info | grep -ohE "[^\s^,]+\sgc"
g1 gc

4.4. Kommandolinjeargumenter

Nogle gange specificerer vi (eller en anden) eksplicit GC-algoritmen, mens vi starter JVM-applikationen. For eksempel vælger vi at bruge ZGC her:

>> java -XX:+UseZGC App

I sådanne tilfælde er der meget enklere måder at finde den brugte GC på. Grundlæggende er alt, hvad vi skal gøre, på en eller anden måde at finde den kommando, som applikationen er blevet udført med .

På UNIX-baserede platforme kan vi f.eks. bruge ps kommando igen:

>> ps -p 48347 -o command=
java -XX:+UseZGC App

Fra ovenstående output er det tydeligt, at JVM bruger ZGC. Tilsvarende jcmd  kommando kan også udskrive kommandolinjeargumenterne :

>> jcmd 48347 VM.flags
84020:
-XX:CICompilerCount=4 -XX:-UseCompressedOops -XX:-UseNUMA -XX:-UseNUMAInterleaving -XX:+UseZGC // omitted

Overraskende nok, som vist ovenfor, vil denne kommando udskrive både implicitte og eksplicitte argumenter og tunables . Så selvom vi ikke specificerer GC-algoritmen eksplicit, vil den vise den valgte og standard:

>> jcmd 48347 VM.flags | grep -ohE '\S*GC\s'
-XX:+UseG1GC

Og endnu mere overraskende, dette vil også fungere på Java 8:

>> jcmd 48347 VM.flags | grep -ohE '\S*GC\s'
-XX:+UseParallelGC

5. Konklusion

I denne artikel så vi forskellige tilgange til at finde den GC-algoritme, der bruges af en bestemt JVM-instans. Nogle af de nævnte tilgange var knyttet til specifikke Java-versioner, og nogle var bærbare.

Desuden så vi et par måder at finde proces-id'et på, hvilket altid er nødvendigt.


Java tag