4. Começando do zero Mestre prático JVM - monitoramento JVM e localização de problemas online

prefácio

Programadores Java entrevistar JVM é quase mais difícil do que fazer perguntas. Perguntas como monitoramento de JVM, OOM online e carga de CPU 100% são frequentemente feitas. Embora possa não ser nossa vez de lidar com problemas online em empresas, seja para entrevistas ou Para lidar com o desenvolvimento, é necessário entender o tratamento de problemas on-line da JVM.

Relativamente falando, seja para resolver o problema de falha ou lidar com gargalos de performance, a ideia geral é mais ou menos a mesma, ou seja: analisar dados (logs), analisar e solucionar problemas, localizar problemas e resolver problemas. dados de execução ou logs Se não conseguirmos, não temos como localizar o problema.

Felizmente, Java enviou ferramentas de monitoramento JVM e instruções relacionadas para nos ajudar a obter dados relacionados a JVM para nos ajudar a solucionar problemas.

instalação de ferramentas

Sabemos apenas que existe uma JVM, mas sua operação parece invisível para nós, então precisamos de ferramentas para monitorar seu status em tempo real, assim como o monitor de desempenho do Windows, o JDK também possui suas próprias ferramentas de visualização. Java fornece 2 ferramentas de monitoramento :

  • D:\opensource\jdk1.8\bin\jconsole.exe

  • D:\opensource\jdk1.8\bin\jvisualvm.exe

jconsole

Digite jconsole através da linha de comando cmd e a seguinte interface aparecerá
insira a descrição da imagem aqui
: Selecione java para entrar e você poderá ver o status da memória, status do carregamento da classe, status do thread etc.
insira a descrição da imagem aqui

Jvisualvm

Executamos cmd, inserimos jvisualvm e iniciamos o Java VisualVM.
insira a descrição da imagem aqui
O menu local à esquerda é o processo java. Depois de selecionar um processo, você pode ver o heap, o status de carregamento da classe e o status pronto à direita.

jvisualvm instala o plug-in GC

O jvisualvm integrado não monitora a função de coleta de lixo do GC, precisamos instalar plug-ins adicionais:

Abra Ferramentas -> Plugins -> Selecione a página "Plugins Disponíveis": Instalamos um Visual GC aqui, para que possamos ver a recuperação de memória e o status de cada geração. Após marcar, clique em Instalar, que é o próximo e regular concordar com o acordo, etc. A rede não é muito estável, às vezes pode demorar mais algumas tentativas. Você pode modificar o endereço do centro de plug-in nas configurações:

insira a descrição da imagem aqui

Modifique o endereço de acordo com as seguintes etapas: Encontre o centro de plug-in

http://visualvm.github.io/pluginscenters.html

[Falha na transferência da imagem do link externo, o site de origem pode ter um mecanismo anti-leeching, é recomendável salvar a imagem e carregá-la diretamente (img-EY48yUBo-1683959030847) (imagem do curso/wps3517.tmp.jpg)]

Encontre a versão correspondente do JDK:

http://visualvm.github.io/archive/uc/8u40/updates.htmlCopiar
[Falha na transferência da imagem do link externo, o site de origem pode ter um mecanismo de link anti-roubo, é recomendável salvar a imagem e carregá-la diretamente (img-GzJYYDpg-1683959030848) (imagem do curso/1638788437854.png)]
endereço do plug-in:
[Falha na transferência da imagem do link externo, o site de origem pode ter um mecanismo anti-leeching, é recomendável salvar a imagem e carregá-la diretamente (img-0IxXMl7y-1683959030849) (imagem do curso/1638788450829.png)]

Instale o plug-in:

[Falha na transferência da imagem do link externo, o site de origem pode ter um mecanismo de link anti-roubo, é recomendável salvar a imagem e carregá-la diretamente (img-uApLHY5r-1683959030849) (imagem do curso/1638788458616.png)]

Em seguida, encontre o Visual GC nos plug-ins disponíveis

Após a conclusão da instalação, fechamos a página de monitoramento atual, abrimos novamente e você pode ver que há uma página adicional do Visual GC atrás do Profiler.

[Falha na transferência da imagem do link externo, o site de origem pode ter um mecanismo anti-leeching, é recomendável salvar a imagem e carregá-la diretamente (img-q7SZdcnx-1683959030850) (imagem do curso/1638788466690.png)]

Aqui podemos ver o tempo de atividade do JIT, o tempo de atividade de carregamento da classe, o tempo de atividade do GC e a situação de cada geração.

Deve-se observar que a versão JDK usada pelo curso atual é 1.8, que ainda vem com o VisualVM. A versão a partir de 1.9 não vem com ele e precisa ser baixada adicionalmente. O endereço do github para download é:

https://visualvm.github.io/download.html

Além disso, se a ferramenta de desenvolvimento usa Intellij IDEA, você pode baixar um plug-in, VisualVM Launcher, e ir diretamente para a página acima por meio da inicialização do plug-in, sem procurar seu próprio projeto na entrada à esquerda.

Claro, existem outras ferramentas, mas este será o principal desenvolvimento da ferramenta de tratamento de falhas tudo-em-um no futuro previsível. Portanto, usaremos esta ferramenta para analisar nossa operação JVM e otimizá-la posteriormente. Para otimizar, nós também precisa Ter uma compreensão mais aprofundada da composição da JVM

Comando de monitoramento da JVM

No ambiente de produção, geralmente encontramos vários problemas de desempenho estranhos. Podemos usar os comandos de monitoramento JVM fornecidos pelo Java para obter efeitos de monitoramento e visualização. Os comandos relacionados são os seguintes

nome efeito principal
jps Exibir processos Java em execução
jstack imprimir instantâneo do segmento
jmap Exportar arquivo de imagem de memória heap
ficar de pé Ver estatísticas jvm
jinfo Visualize e modifique os parâmetros de configuração do jvm em tempo real
Jhat Usado para analisar arquivos de despejo de pilha

jps ver progresso

jps pode listar os processos Java em execução e exibir o nome da classe principal (Main Class, a classe onde a função main() está localizada) da máquina virtual e o id do processo, e os parâmetros podem ser visualizados através de jps -help

opções efeito
-q Apenas imprima o ID do processo
-m Saída dos parâmetros passados ​​para a função principal da classe principal
-eu Emita o nome completo da classe principal, se o processo executar o pacote Jar, emita o nome do pacote jar
-v O parâmetro jvm especificado quando o programa inicia

Apresentação do caso:
insira a descrição da imagem aqui

jstack: imprime instantâneo do thread

Geralmente, no ambiente de produção, se ocorrerem problemas como pausa de longo prazo, travamento, impasse e tempo de solicitação longo, você pode analisar e localizar o problema imprimindo instantâneos de encadeamento. O seguinte é um código de impasse:

public class DeadlockExample {
    
    
    private static Object lock1 = new Object();
    private static Object lock2 = new Object();
     public static void main(String[] args) {
    
    
        Thread t1 = new Thread() {
    
    
            public void run() {
    
    
                synchronized (lock1) {
    
    
                    System.out.println("Thread 1 acquired lock 1");
                    try {
    
    
                        Thread.sleep(1000);
                        synchronized (lock2) {
    
    
                            System.out.println("Thread 1 acquired lock 2");
                        }
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
            }
        };
         Thread t2 = new Thread() {
    
    
            public void run() {
    
    
                synchronized (lock2) {
    
    
                    System.out.println("Thread 2 acquired lock 2");
                    try {
    
    
                        Thread.sleep(1000);
                        synchronized (lock1) {
    
    
                            System.out.println("Thread 2 acquired lock 1");
                        }
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
            }
        };
         t1.start();
         t2.start();
         try {
    
    
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
    }
}

Em seguida, tentamos jps -l para visualizar o processo primeiro
insira a descrição da imagem aqui
, obter a identificação do processo e usar jstack para visualizar cada instantâneo de encadeamento: jstack 27928
insira a descrição da imagem aqui
No instantâneo de encadeamento, você pode ver todos os encadeamentos no processo atual. Entre eles estão os threads do nosso código e o estado está bloqueado. Ao mesmo tempo, ele solicita encontrado 1 impasse para encontrar um impasse e fornece o local onde ocorreu o impasse.

jmap: exportar instantâneo da pilha

A execução jmap -histo pidpode imprimir o número de instâncias e uso de memória de cada classe no heap atual, como segue, nome da classe é o nome da classe de cada classe ([B é o tipo de byte, [C é o tipo de char, [I é o tipo int) , bytes É o tamanho da memória ocupada por todos os exemplos desta classe, e instances é o número de instâncias desta classe:
insira a descrição da imagem aqui
execute jmap -dump para despejar o instantâneo da memória heap em um arquivo especificado, como executar

jmap -dump:format=b,file=/data/jvm/dumpfile_jmap.hprof PID , você pode despejar o instantâneo da memória heap atual no arquivo dumpfile_jmap.hprof e, em seguida, analisar o instantâneo da memória.

Geralmente configuramos o ambiente de produção para que a máquina virtual gere automaticamente um arquivo de despejo após a ocorrência de uma exceção OOM

-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/Users

Por exemplo, há um loop infinito de código e executá-lo por um determinado período de tempo causará estouro de memória

public class Main {
    
    
    public static void main(String[] args) {
    
    
        ArrayList arrayList = new ArrayList();
        int i = 0;
        while(true){
    
    
            arrayList.add(new Main());
            System.out.println(i++);
        }
    }
}

Para o efeito óbvio, definimos o heap para ser menor e, em seguida, definimos HeapDumpOnOutOfMemoryError em

-Xms2m
-Xmx2m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=d:\

Defina os parâmetros de VM acima para o aplicativo atual e o efeito da execução do código é o seguinte
insira a descrição da imagem aqui
Em seguida, encontramos o arquivo de instantâneo de heap hprof, que pode ser carregado e analisado por meio da ferramenta jvisualvm.
insira a descrição da imagem aqui
Agora, o arquivo de instantâneo, o tipo de arquivo precisa ser selecionado como um instantâneo de heap.
insira a descrição da imagem aqui
Após o carregamento, você pode ver diretamente a mensagem de erro de estouro de memória
insira a descrição da imagem aqui
Depois de clicar no nome do encadeamento principal, você pode localizar diretamente o local do estouro de memória
insira a descrição da imagem aqui

jstat: monitora as informações da máquina virtual

jstat -gc pid 500 10: pid é o ID do encadeamento e imprime o status do heap Java a cada 500 milissegundos (capacidade, capacidade de uso, tempo gc, etc. de cada área). Imprimindo 10 vezes jstat também pode monitorar o tamanho da memória de cada área e monitorar a classe carregando informações de outros ângulos.
insira a descrição da imagem aqui
Especificamente, você pode pesquisar no Google o uso detalhado de jstat. A seguir está a comparação do resultado

S0C: o tamanho da primeira área sobrevivente
S1C: o tamanho da segunda área sobrevivente
S0U: o tamanho usado da primeira área sobrevivente
S1U: o tamanho usado da segunda área sobrevivente
EC: o tamanho da área Eden
EU: o uso da área do Éden Tamanho
OC: Tamanho da Geração Antiga
OU: Tamanho do Uso da Geração Antiga
MC: Tamanho da Área do Método
MU: Tamanho do Uso da Área do Método
CCSC: Tamanho do Espaço de Classe Comprimido CCSU
: Tamanho do Uso do Espaço de Classe Comprimido
YGC: Tempos de Coleta de Lixo da Geração Jovem
YGCT: Jovem Tempo de Consumo de Coleta de Lixo de Geração
FGC: Tempos de coleta de lixo de geração antiga
FGCT: Tempo de coleta de lixo de geração antiga
GCT: Tempo total de coleta de lixo
Unidade: KB

jinfo: ver parâmetros do processo

jinfo(Configuration Info for Java) Verifique os parâmetros de configuração da máquina virtual e também pode ser usado para ajustar os parâmetros de configuração da máquina virtual.

Em muitos casos, os aplicativos Java não especificam todos os parâmetros da máquina virtual Java. Neste momento, os desenvolvedores podem não saber o valor padrão de um parâmetro específico da máquina virtual Java. Nesse caso, pode ser necessário obter o valor padrão de um parâmetro consultando a documentação. Este processo de pesquisa pode ser muito difícil. Mas com a ferramenta jinfo, os desenvolvedores podem encontrar facilmente o valor atual dos parâmetros da máquina virtual Java.

jinfo pode não apenas visualizar o valor real de um determinado parâmetro da máquina virtual Java em tempo de execução, mas também modificar alguns parâmetros em tempo de execução e fazê-los entrar em vigor imediatamente. No entanto, nem todos os parâmetros suportam modificação dinâmica. Os parâmetros só podem ser modificados em tempo real com o sinalizador marcado gerenciável. Na verdade, essa capacidade de modificação é extremamente limitada.
insira a descrição da imagem aqui

Sinalizadores de VM:
Sinalizadores de VM não padrão: -XX:CICompilerCount=12 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=null -XX:InitialHeapSize=2097152 -XX:MaxHeapSize=209715200 -XX:MaxNewSize=69730304 -XX:Min HeapDeltaBytes = 524288 -XX:OldSize=524288 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Linha de comando: -Xms2m -Xmx200m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d: \ -javaagent:D:\Arquivos de Programas\JetBrains\IntelliJ IDEA 2022.2.1\lib\idea_rt.jar=54817:D:\Arquivos de Programas\JetBrains\IntelliJ IDEA 2022.2.1\bin -Dfile.encoding=UTF-8

Por meio de jinfo -flags pid: visualize o valor do parâmetro ao qual foi atribuído um valor

insira a descrição da imagem aqui
jinfo pode não apenas visualizar o valor real de um determinado parâmetro da máquina virtual Java em tempo de execução, mas também modificar alguns parâmetros em tempo de execução e fazê-los entrar em vigor imediatamente. No entanto, nem todos os parâmetros suportam modificação dinâmica. Os parâmetros só podem ser modificados em tempo real com o sinalizador marcado gerenciável. Você pode usar o comando java -XX:+PrintFlagsInitial | grep manageable para visualizar o
insira a descrição da imagem aqui
formato de modificação gerenciável da seguinte forma:

  • Para modificação do tipo booleano: jinfo -flag ±parameter pid
  • Para tipos não booleanos: jinfo -flag nome do parâmetro=valor do parâmetro pid

Por exemplo, modifique e imprima a demonstração do log do GC da seguinte forma: jinfo -flag +PrintGCDetails PID

//查看进程
C:\Users\Administrator>jps -l
20924 org.example.Main
...

//查看是否设置PrintGCDetails参数配置
C:\Users\Administrator>jinfo -flag PrintGCDetails 20924

//增加jvm参数:打印GC详情
C:\Users\Administrator>jinfo -flag +PrintGCDetails 20924

//查看是否设置PrintGCDetails参数配置
C:\Users\Administrator>jinfo -flag PrintGCDetails 20924
-XX:+PrintGCDetails
...

Resolva o problema on-line CPU100%

Geralmente, 100% da CPU é basicamente causada por um loop infinito de código. A ideia central da investigação é encontrar o servidor correspondente, localizar quais códigos em qual thread de qual processo causou o problema e apresentar brevemente os exemplos de códigos anormais naquele momento.

A primeira etapa é encontrar o processo que consome mais CPU: use top -c para visualizar o processo e, em seguida, insira o P grande para classificar de acordo com o uso da CPU.
insira a descrição da imagem aqui
O segundo passo é encontrar a thread que mais consome CPU no processo: encontre o processo com maior CPU, encontre o ID do processo (PID), encontre a thread correspondente a este processo através do comando top -Hp PID, e então digite o grande P para classificar de acordo com o uso da CPU.
insira a descrição da imagem aqui
Obtenha o primeiro PID é o ID do encadeamento que consome mais tempo e, em seguida, use printf "%x\n" PID para converter o PID de decimal para hexadecimal (o motivo para converter para hexadecimal é porque na pilha, O id do encadeamento é expresso em hexadecimal.)

[root@VM-4-2-centos ~]# printf "%x\n" 13759
35bf

Em seguida, precisamos usar o jstack para imprimir as informações da pilha do processo e, em seguida, usar o grep para visualizar as coisas relacionadas ao thread correspondentes. ID do processo jstack | grep "ID do thread" -C5 --color

jstack 30979  | grep "35bf" -C5 --color

Neste momento, você pode imprimir o código e, em seguida, combinar o nid do instantâneo do thread impresso, localizar qual thread é demorado e, ao mesmo tempo, localizar rapidamente o código, você pode ver qual método em qual classe causou a CPU 100% do motivo.
insira a descrição da imagem aqui

Monitoramento remoto

Se você não estiver muito familiarizado com comandos, é difícil usar comandos para monitorar a JVM. JVisualvm fornece a função remota jmx. O padrão é fornecer serviços RMI por meio do endereço IP do localhost, o que exige que configuremos os parâmetros da JVM remotamente para permitir conexões remotas

-Xms256m 
-Xmx512m 
-Xss256m 
-XX:PermSize=512m 
-XX:MaxPermSize=1024m 

-Dcom.sun.management.jmxremote 
-Djava.rmi.server.hostname=服务器IP 
#远程服务的端口:
-Dcom.sun.management.jmxremote.port=9015 
#客户端 rmi通信端口
-Dcom.sun.management.jmxremote.rmi.port=9015 
#关闭ssl功能
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false 

Em seguida, adicionamos o host remoto no Jvisualvm local
insira a descrição da imagem aqui
e, em seguida, adicionamos a conexão remota jmx
insira a descrição da imagem aqui
para definir os parâmetros de conexão remota e cancelar a conexão ssl. ss
O artigo acabou. Se for útil para você, faça uma boa revisão. Seu encorajamento é minha maior motivação

Acho que você gosta

Origin blog.csdn.net/u014494148/article/details/130657041
Recomendado
Clasificación