Ferramenta de linha de comando para encontrar o tamanho do heap Java e a memória usada (Linux)?

171

Existe uma ferramenta de linha de comando (Linux) para verificar o tamanho da pilha (e a memória usada) de um aplicativo Java?

Eu tentei através do jmap. Mas dá informações. sobre áreas de memória interna como Eden / PermGen etc., o que não é útil para mim.

Estou procurando algo como:

  • Memória máxima: 1GB
  • Memória mínima: 256 MB
  • Memória de pilha: 700 MB
  • Memória usada: 460 MB

Isso é tudo. Sei que posso ver isso no JConsole etc., mas preciso de uma ferramenta de linha de comando (não é possível ativar o JMX etc.)

Você conhece alguma dessas ferramentas / comandos?

Jaspe
fonte

Respostas:

149

Cada processo Java possui um pid, que você primeiro precisa encontrar com o jpscomando

Depois de ter recebido o pid, você pode usar jstat -gc [insert-pid-here]para encontrar estatísticas do comportamento do heap coletado de lixo.

  • jstat -gccapacity [insert-pid-here] apresentará informações sobre geração de pool de memória e recursos de espaço.

  • jstat -gcutil [insert-pid-here]apresentará a utilização de cada geração como um percentual de sua capacidade. Útil para obter uma visão geral do uso.

Veja os documentos do jstat no site da Oracle.

farmer1992
fonte
11
Existe uma recomendação que opções jstatdevem ser usadas para verificar apenas o uso geral de memória de uma JVM? Digamos que você inicie a JVM Xms=4ge Xmx=4gdeseje ver quanta memória já está sendo usada?
precisa saber é o seguinte
1
"jstat -gcutil <pid> 250 N" foi muito útil para coletar N amostras com intervalos de 250ms e exibir a saída como porcentagens para os espaços correspondentes. Obrigado.
Kerem
3
Digno de nota citação jstatda Oracle Java 8 manual de página : This command is experimental and unsupported.
Patryk.beza
1
awk 'print {$3+$4+$6+$8}'pode imprimir o uso resumidos em colunas jstat de Java 8
cybersoft
Tive problemas com as outras respostas, mas um básico ps -ef | grep javame mostrou os vm args, que no meu caso incluíam o valor -Xmx, que era tudo o que eu precisava.
Xdhmoore # 23/17
66

jvmtop é uma ferramenta de linha de comando que fornece uma visualização ao vivo em várias métricas, incluindo heap.

Exemplo de saída do modo de visão geral da VM:

 JvmTop 0.3 alpha (expect bugs)  amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46
MRalwasser
fonte
É realmente uma ótima ferramenta, tipo htop, mas com métricas do jstat. Obrigado pela sugestão, @MRalwasser.
Oski86
65

Este comando mostra os tamanhos de heap configurados em bytes.

java -XX:+PrintFlagsFinal -version | grep HeapSize

Também funciona no Amazon AMI no EC2.

Atma
fonte
27
Isso não responde à pergunta, que pergunta especificamente como verificar o uso de heap de um processo. O comando aqui lista os padrões da JVM em todos os processos.
Madbreaks
10
No entanto, é uma resposta muito útil para mim, que chego a esta página através da pesquisa no google sobre como encontrar o tamanho global da pilha.
Johan
@jumping_monkey não indireto, incorreto. Se o que você está dizendo é verdade, a resposta deve ser editada ou você deve adicionar uma nova resposta.
Madbreaks
42

Tente isso, funcionou no Ubuntu e RedHat:

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'

Para Windows:

java -XX:+PrintFlagsFinal -version | findstr /i "HeapSize PermSize ThreadStackSize"

Para Mac

java -XX:+PrintFlagsFinal -version | grep -iE 'heapsize|permsize|threadstacksize'

A saída de todos esses comandos se assemelha à saída abaixo:

uintx InitialHeapSize                          := 20655360        {product}
uintx MaxHeapSize                              := 331350016       {product}
uintx PermSize                                  = 21757952        {pd product}
uintx MaxPermSize                               = 85983232        {pd product}
intx ThreadStackSize                           = 1024            {pd product}
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

Para encontrar o tamanho em MB, divida o valor com (1024 * 1024).

padippist
fonte
Como encontrar o uso de memória separado por heap, tamanho permanente, ... do processo java específico por pid?
Gary Gauh
3
@GaryGauh Este é o tamanho padrão da pilha. Para encontrar o uso do aplicativo em execução, faça-o dentro do código ou use o jconsole. É isso que sei que também deve haver muitas outras maneiras.
padippist
2
Use jstat -gc <vmid>para aplicativos em execução.
Micha Wiedenmann
27

Sem usar o JMX, que é o que a maioria das ferramentas usa, tudo o que você pode fazer é usar

jps -lvm

e inferir que as configurações serão a partir das opções da linha de comando.

Você não pode obter informações dinâmicas sem o JMX por padrão, mas pode escrever seu próprio serviço para fazer isso.

BTW: Prefiro usar o VisualVM em vez do JConsole.

Peter Lawrey
fonte
25

Existe uma ferramenta de linha de comando com um aspecto visual - jvm-mon . É uma ferramenta de monitoramento da JVM para a linha de comandos que desativa:

  • uso de pilha, tamanho e max
  • processos jvm
  • uso de CPU e GC
  • tópicos principais

As métricas e os gráficos são atualizados enquanto a ferramenta está aberta.

Amostra: jvm-mon

Andrejs
fonte
1
Apenas a nota que corre jvm-mon única para Java8
tmanolatos
1
^ Há uma nova versão que agora também suporta Java 11.
Andrejs
11

Tarde na festa, mas uma solução muito simples é usar o script jpsstat.sh. Ele fornece uma simples memória atual ao vivo , memória máxima e detalhes de uso da CPU .

  • Goto projeto GitHub e baixar o jpsstat.sh arquivo
  • Clique com o botão direito do mouse na guia jpsstat.sh e vá para permissões e torne-o executável
  • Agora, execute o script usando o seguinte comando ./jpsstat.sh

Aqui está o exemplo de saída do script -

=====  ======  =======  =======  =====
 PID    Name   CurHeap  MaxHeap  %_CPU
=====  ======  =======  =======  =====
2777   Test3      1.26     1.26    5.8
2582   Test1      2.52     2.52    8.3
2562   Test2      2.52     2.52    6.4
amarjeetAnand
fonte
não parecem funcionar fora da caixa em um SUSE Linux (linha 38: declare: -A: opção inválida)
Chris
parece que você recebeu um erro na declaração de matriz associativa que precisa do bash> = 4. Outro problema pode estar relacionado à execução do script como "sh jpsstat.sh". Nesse caso, tente executar o script como "./jpsstat.sh".
amarjeetAnand
9

No meu caso, eu precisava verificar as bandeiras dentro de um contêiner de docker que não possuía a maioria dos utilitários básicos (ps, pstree ...)

Usando jps, obtive o PID da JVM em execução (no meu caso 1) e, em seguida jcmd 1 VM.flags, obtive os sinalizadores da JVM em execução.

Depende de quais comandos você tem disponível, mas isso pode ajudar alguém. :)

froblesmartin
fonte
8

A partir do Java8 e superior , você pode usar o comando abaixo:

jcmd JAVA_PROCESS_IDGC.heap_info

Você pode consultar a soma da memória total e usada da saída.

Sample Command And Output: jcmd 9758 GC.heap_info

PSYoungGen  total 1579520K, used 487543K [0x0000000751d80000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 1354240K, 36% used [0x0000000751d80000,0x000000076f99dc40,0x00000007a4800000)
  from space 225280K, 0% used [0x00000007b2400000,0x00000007b2400000,0x00000007c0000000)
  to   space 225280K, 0% used [0x00000007a4800000,0x00000007a4800000,0x00000007b2400000)
ParOldGen       total 3610112K, used 0K [0x0000000675800000, 0x0000000751d80000, 0x0000000751d80000)
  object space 3610112K, 0% used [0x0000000675800000,0x0000000675800000,0x0000000751d80000)
Metaspace       used 16292K, capacity 16582K, committed 16896K, reserved 1064960K
  class space    used 1823K, capacity 1936K, committed 2048K, reserved 1048576K

Para obter mais detalhes sobre o comando jcmd, visite o link: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html

vaibhav gupta
fonte
1
Você precisa corrigir seu comentário. GC.heap_info está disponível no Java 9 e acima. Ele não está disponível no Java 8. Veja outro thread aqui: stackoverflow.com/questions/41891127/…
Pavel Molchanov
@PavelMolchanov Consigo usar o comando no jdk1.8.0_172. /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/bin/jcmd 98270 GC.heap_info. Por favor, se puder, adicione as informações ao tópico referido, assim como não tenho reputação suficiente no momento para adicionar um comentário.
vaibhav gupta
Você usa Mac? Você usa o Oracle JDK? Não sei como ele pode estar disponível no seu jdk1.8.0_172. O Oracle documentou esse recurso apenas no Java 9 e superior: docs.oracle.com/javase/9/tools/jcmd.htm . Não está na documentação do Oracle JDK para Java 8. Não está mencionado no link que você forneceu na parte inferior: docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/…
Pavel Molchanov
Mais uma pergunta. Por favor, verifique a versão do JDK que está executando o processo 98270 no seu exemplo. O jcmd obtém comandos disponíveis da JVM do processo (no seu caso 98270). Se o processo 98270 for executado com JDK diferente (JDK 9 ou superior), você verá o comando GC.heap_info disponível mesmo no JCMD em Java 8. Os comandos disponíveis podem ser diferentes para diferentes processos. Para obter comandos disponíveis, execute: jcmp <PID> help.
Pavel Molchanov
1
FWIW, também GC.heap_infoestá definitivamente disponível no OpenJDK 8. Talvez apenas em versões recentes? Estou usando este: 8u191-b12-2ubuntu0.18.04.1
Por Lundberg
7

Qualquer abordagem deve fornecer aproximadamente o mesmo número. É sempre uma boa idéia alocar o heap usando -X..m -X..xpara todas as gerações. Você pode garantir e também fazer ps para ver quais parâmetros foram passados ​​e, portanto, estão sendo usados.

Para usos reais de memória, é possível comparar aproximadamente VIRT (alocado e compartilhado) e RES (real usado) com os valores jstat:

Para Java 8, consulte jstat para esses valores realmente significam. Supondo que você execute uma classe simples sem mmap ou processamento de arquivo.

$ jstat -gccapacity 32277
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
215040.0 3433472.0  73728.0  512.0  512.0  67072.0   430080.0  6867968.0   392704.0   392704.0      0.0 1083392.0  39680.0      0.0 1048576.0   4864.0   7225     2
$ jstat -gcutil 32277
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  6.25   0.00   7.96  18.21  98.01  95.29   7228   30.859     2    0.173   31.032

Máx :

     NGCMX + S0C + S1C + EC    + OGCMX   + MCMX    + CCSMX
   3433472 + 512 + 512 + 67072 + 6867968 + 1083392 + 1048576 = 12 GB

(aproximadamente perto e abaixo da memória VIRT)

Máx. (Mín., Usado):

215040 + 512 + 512 + 67072 + 430080  + 39680    +  4864  = ~ 1GB

(aproximadamente perto da memória RES)

"Não me cite sobre isso", mas o mem VIRT está aproximadamente próximo ou superior à memória máxima alocada, mas enquanto a memória utilizada estiver disponível / disponível na memória física, a JVM não emitirá exceção de memória. De fato, a memória máxima nem é verificada em relação à memória física na inicialização da JVM, mesmo com a troca desativada no SO. Uma explicação melhor sobre o que a memória virtual realmente usou por um processo Java é discutida aqui .

kisna
fonte
4

Primeiro, obtenha a identificação do processo, o primeiro número do processo listado, de uma das seguintes maneiras: (ou use apenas ps aux | grep java, se preferir)

jps -lvm

Em seguida, use o ID do processo aqui:

jmap -heap $MY_PID 2>/dev/null | sed -ne '/Heap Configuration/,$p';
jmap -permstat $MY_PID
sjas
fonte
2

Usar o topcomando é a maneira mais simples de verificar o uso de memória do programa. RESA coluna mostra a memória física real que é ocupada por um processo.

No meu caso, eu tinha um arquivo 10g lido em java e cada vez que saí da exceção OutOfMemory. Isso aconteceu quando o valor na REScoluna atingiu o valor definido na -Xmxopção Então, aumentando a memória usando a -Xmxopção, tudo correu bem.

M. Mashaye
fonte
3
O comando top está mostrando quanto sistema operacional é fornecido à JVM. esse pessoal está perguntando como podemos ver o uso do espaço de heap dentro da JVM. A JVM está usando 10g não significa que o espaço de heap real esteja cheio de dados de 10g, porque a jvm quase nunca retorna a memória para o SO a partir do heap até que você finalize o processo.
linehrr
2

Em termos de tamanho de heap Java, no Linux, você pode usar

ps aux | grep java

ou

ps -ef | grep java

e procure -Xms, -Xmx para descobrir o tamanho de heap inicial e máximo especificado.

No entanto, se -Xms ou -Xmx estiver ausente no processo Java em que você está interessado, isso significa que seu processo Java está usando os tamanhos de heap padrão. Você pode usar o seguinte comando para descobrir os tamanhos padrão.

java -XX:+PrintFlagsFinal -version | grep HeapSize

ou uma jvm específica, por exemplo,

/path/to/jdk1.8.0_102/bin/java -XX:+PrintFlagsFinal -version | grep HeapSize

e procure InitialHeapSize e MaxHeapSize, que está em bytes.

Yuci
fonte
1

Se estiver usando o jrockit, tente a ferramenta de linha de comando jrcmd. Por exemplo:

$ jrcmd 5127 print_memusage
5127:
Total mapped                  1074596KB           (reserved=3728KB)
-              Java heap       786432KB           (reserved=0KB)
-              GC tables        26316KB          
-          Thread stacks        13452KB           (#threads=34)
-          Compiled code         9856KB           (used=9761KB)
-               Internal          840KB          
-                     OS        15036KB          
-                  Other       146632KB          
-        Java class data        75008KB           (malloced=74861KB #103221 in 18709 classes)
- Native memory tracking         1024KB           (malloced=102KB #8)

Para mais comandos, como heap_diagnostics, use "jrcmd help" para listá-los.

https://blogs.oracle.com/jrockit/entry/why_is_my_jvm_process_larger_t

convidado
fonte
1
jstat -gccapacity javapid  (ex. stat -gccapacity 28745)
jstat -gccapacity javapid gaps frames (ex.  stat -gccapacity 28745 550 10 )

O / P de amostra do comando acima

NGCMN    NGCMX     NGC     S0C  
87040.0 1397760.0 1327616.0 107520.0 

NGCMN   Minimum new generation capacity (KB).
NGCMX   Maximum new generation capacity (KB).
NGC Current new generation capacity (KB).

Obtenha mais detalhes sobre isso em http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html

Pravin
fonte
1

Até o momento, não existe essa ferramenta para imprimir a memória heap no formato solicitado. A única maneira de imprimir é escrever um programa java com a ajuda da Runtime Class ,

public class TestMemory {

public static void main(String [] args) {

    int MB = 1024*1024;

    //Getting the runtime reference from system
    Runtime runtime = Runtime.getRuntime();

    //Print used memory
    System.out.println("Used Memory:" 
        + (runtime.totalMemory() - runtime.freeMemory()) / MB);

    //Print free memory
    System.out.println("Free Memory:" 
        + runtime.freeMemory() / mb);

    //Print total available memory
    System.out.println("Total Memory:" + runtime.totalMemory() / MB);

    //Print Maximum available memory
    System.out.println("Max Memory:" + runtime.maxMemory() / MB);
}

}

referência: https://viralpatel.net/blogs/getting-jvm-heap-size-used-memory-total-memory-using-java-runtime/

Gowtham Prasath
fonte
isto está errado. jmap -heap <pid> fornece esta informação
vsingh 10/07
0

Encontre a identificação do processo do seu processo webapp / java de cima. Use jmap heap para obter a alocação de heap. Eu testei isso no AWS-Ec2 para pé de feijão elástico

Você pode ver na imagem abaixo a pilha máxima de 3 GB para o aplicativo

insira a descrição da imagem aqui

vsingh
fonte