Expliquei muito sobre a estrutura de memória da JVM e a criação de objetos. Essas são a base da JVM, mas o objetivo final é poder ajustá-la. Às vezes, o aplicativo falha em responder e relata OOM, ou vazamentos de memória, ou morte. Para resolver Para esses problemas, é indispensável aprender algumas ferramentas de linha de comando que vêm com o jdk. Com a base dessas ferramentas, você não só reiniciará para resolver o problema quando encontrar um problema, mas poderá começar em Resolva os problemas do aplicativo em a causa raiz, melhorando assim o poder interno do desenvolvimento Java
De um modo geral, as ferramentas jdk comumente usadas são as seguintes:
- jps: ver todos os processos java
- jstat: monitora várias informações de status operacional de máquinas virtuais
- jinfo: Visualize e ajuste vários parâmetros da máquina virtual em tempo real
- jmap: Gerar instantâneo de armazenamento de heap
- jhat: Analise o arquivo heapdump
- jstack: Gera um instantâneo de thread da máquina virtual no momento atual
Um, o JDK vem com ferramentas
jps
: Veja todos os processos Java
jps
(JVM Process Status) command ps
comandos semelhantes ao UNIX .
jps
: Exibe o nome da classe principal de execução da máquina virtual e o ID exclusivo (Local Virtual Machine Identifier, LVMID) desses processos.
jps -q
: Produza apenas o ID exclusivo da máquina virtual local do processo.
jps -l
: Exibe o nome completo da classe principal.Se o processo estiver executando o pacote Jar, exiba o caminho Jar.
jps -v
: Envia os parâmetros JVM quando o processo da máquina virtual é iniciado.
jps -m
: Envie os parâmetros passados para a função main () do processo Java.
jstat
: Monitore várias informações de status operacional de máquinas virtuais
jstat (JVM Statistics Monitoring Tool) é uma ferramenta de linha de comando usada para monitorar várias informações de status operacional de máquinas virtuais. Ele pode exibir informações de classe, memória, coleta de lixo, compilação JIT e outros dados em execução no processo da máquina virtual local ou remotamente (requer suporte RMI do host remoto). Em um servidor que não tem uma GUI e fornece apenas um texto simples ambiente de console, será a ferramenta de escolha para localizar problemas de desempenho da máquina virtual durante a operação.
jstat
Formato de comando:
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
Por exemplo, jstat -gc -h3 31736 1000 10
mostra um processo de análise com a caixa id 31736 gc, o registro é impresso uma vez a cada 1000ms, 10 vezes para interromper a impressão, os indicadores de impressão devem ser impressos a cada três linhas.
As opções comuns são as seguintes:
jstat -class vmid
: Exibir informações relacionadas ao ClassLoader;jstat -compiler vmid
: Exibir informações relacionadas à compilação JIT;jstat -gc vmid
: Exibir informações de heap relacionadas ao GC;jstat -gccapacity vmid
: Exibe a capacidade e o uso de cada geração;jstat -gcnew vmid
: Exibe informações da nova geração;jstat -gcnewcapcacity vmid
: Exibe o tamanho e o uso da nova geração;jstat -gcold vmid
: Exibe as estatísticas de comportamento da geração anterior e da geração permanente. A partir de jdk1.8, esta opção indica apenas a geração anterior porque a geração permanente foi removida;jstat -gcoldcapacity vmid
: Mostra o tamanho da velhice;jstat -gcpermcapacity vmid
: Exibe o tamanho da geração permanente. A partir de jdk1.8, esta opção não existe mais porque a geração permanente foi removida;jstat -gcutil vmid
: Exibir informações de coleta de lixo;
Além disso, com -t
os parâmetros listados podem ser adicionados em um registro de data e hora, a informação é gerada para exibir o tempo de execução do programa.
jinfo
: Visualize e ajuste vários parâmetros da máquina virtual em tempo real
jinfo vmid
: Saída de todos os parâmetros e atributos do sistema do processo JVM atual (a primeira parte são os atributos do sistema e a segunda parte são os parâmetros JVM).
jinfo -flag name vmid
: Produz o valor específico do parâmetro correspondente ao nome. Por exemplo, produza MaxHeapSize e verifique se o processo jvm atual está habilitado para imprimir logs de GC ( -XX:PrintGCDetails
: modo de log de GC detalhado, ambos desabilitados por padrão).
C:\Users\SnailClimb>jinfo -flag MaxHeapSize 17340
-XX:MaxHeapSize=2124414976
C:\Users\SnailClimb>jinfo -flag PrintGC 17340
-XX:-PrintGC
Usando jinfo, você pode modificar dinamicamente os parâmetros de jvm sem reiniciar a máquina virtual. Especialmente o ambiente online é particularmente útil, por favor, veja o seguinte exemplo:
jinfo -flag [+|-]name vmid
Ative ou desative o parâmetro do nome correspondente.
C:\Users\SnailClimb>jinfo -flag PrintGC 17340
-XX:-PrintGC
C:\Users\SnailClimb>jinfo -flag +PrintGC 17340
C:\Users\SnailClimb>jinfo -flag PrintGC 17340
-XX:+PrintGC
jmap
: Gerar instantâneo de despejo de heap
jmap
O comando (Memory Map for Java) é usado para gerar instantâneos de despejo de heap. Se você não usar o jmap
comando, a fim de obter o dump de heap Java, você pode usar “-XX:+HeapDumpOnOutOfMemoryError”
parâmetros, permitindo que as máquinas virtuais gerem arquivos de dump automaticamente após a ocorrência da exceção OOM, o comando Linux pode kill -3
sair do processo pode enviar um sinal para obter o dump Arquivo.
jmap
A função de não é apenas obter o arquivo de despejo, ele também pode consultar a fila de execução do finalizador, heap Java e informações detalhadas de geração permanente, como uso de espaço, qual coletor é usado atualmente, etc. E jinfo
, como jmap
há muitos recursos na plataforma Windows, ela também é restrita.
Exemplo: saída de um instantâneo de heap de um aplicativo especificado para a área de trabalho. Posteriormente, você pode analisar o arquivo heap com ferramentas como jhat e Visual VM.
C:\Users\SnailClimb>jmap -dump:format=b,file=C:\Users\SnailClimb\Desktop\heap.hprof 17340
Dumping heap to C:\Users\SnailClimb\Desktop\heap.hprof ...
Heap dump file created
jhat
: Analise o arquivo heapdump
jhat
Usado para analisar o arquivo heapdump, ele estabelecerá um servidor HTTP / HTML para que os usuários possam visualizar os resultados da análise no navegador.
C:\Users\SnailClimb>jhat C:\Users\SnailClimb\Desktop\heap.hprof
Reading from C:\Users\SnailClimb\Desktop\heap.hprof...
Dump file created Sat May 04 12:30:31 CST 2019
Snapshot read, resolving...
Resolving 131419 objects...
Chasing references, expect 26 dots..........................
Eliminating duplicate references..........................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
Visite http: // localhost: 7000 /
jstack
: Gerar um instantâneo de thread da máquina virtual no momento atual
jstack
O comando (Stack Trace for Java) é usado para gerar um instantâneo de thread da máquina virtual no momento atual. Um instantâneo de thread é uma coleção de pilhas de métodos sendo executadas por cada thread na máquina virtual atual.
O objetivo de gerar um instantâneo do encadeamento é principalmente localizar a causa do encadeamento travado por um longo tempo, como impasse entre encadeamentos, loops infinitos e longas esperas causadas pela solicitação de recursos externos, que são todos motivos para o encadeamento travar muito tempo. Quando um encadeamento está paralisado, jstack
observando a pilha de chamadas de cada encadeamento, você pode saber o que o encadeamento que não responde está fazendo em segundo plano ou quais recursos ele está esperando.
Abaixo está o código para um bloqueio de thread. Aqui, passaremos jstack
um comando para verificar o impasse, as informações de saída do impasse e encontrar o impasse do encadeamento.
public class DeadLockDemo {
private static Object resource1 = new Object();//资源 1
private static Object resource2 = new Object();//资源 2
public static void main(String[] args) {
new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource2");
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
}
}
}, "线程 1").start();
new Thread(() -> {
synchronized (resource2) {
System.out.println(Thread.currentThread() + "get resource2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread() + "waiting get resource1");
synchronized (resource1) {
System.out.println(Thread.currentThread() + "get resource1");
}
}
}, "线程 2").start();
}
}
Resultado
Thread[线程 1,5,main]get resource1
Thread[线程 2,5,main]get resource2
Thread[线程 1,5,main]waiting get resource2
Thread[线程 2,5,main]waiting get resource1
O thread A obtém o bloqueio do monitor do resource1 por meio de synchronized (resource1) e, em seguida, Thread.sleep(1000);
suspende o thread A por 1s para permitir que o thread B seja executado e, em seguida, obter o bloqueio do monitor do resource2. O Thread A e o Thread B começam a solicitar recursos um do outro após terem terminado de hibernar e, em seguida, os dois threads entrarão em um estado de espera um do outro, o que também produz um deadlock.
Por jstack
análise de comando:
C:\Users\SnailClimb>jps
13792 KotlinCompileDaemon
7360 NettyClient2
17396
7972 Launcher
8932 Launcher
9256 DeadLockDemo
10764 Jps
17340 NettyServer
C:\Users\SnailClimb>jstack 9256
Parte da saída é a seguinte:
Found one Java-level deadlock:
=============================
"线程 2":
waiting to lock monitor 0x000000000333e668 (object 0x00000000d5efe1c0, a java.lang.Object),
which is held by "线程 1"
"线程 1":
waiting to lock monitor 0x000000000333be88 (object 0x00000000d5efe1d0, a java.lang.Object),
which is held by "线程 2"
Java stack information for the threads listed above:
===================================================
"线程 2":
at DeadLockDemo.lambda$main$1(DeadLockDemo.java:31)
- waiting to lock <0x00000000d5efe1c0> (a java.lang.Object)
- locked <0x00000000d5efe1d0> (a java.lang.Object)
at DeadLockDemo$$Lambda$2/1078694789.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"线程 1":
at DeadLockDemo.lambda$main$0(DeadLockDemo.java:16)
- waiting to lock <0x00000000d5efe1d0> (a java.lang.Object)
- locked <0x00000000d5efe1c0> (a java.lang.Object)
at DeadLockDemo$$Lambda$1/1324119927.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
Você pode ver que jstack
o comando nos ajudou a obter o impasse do thread de detalhes.