Como monitorar o uso de memória Java?

temos uma aplicação j2ee a correr no Jboss e queremos monitorizar o seu uso de memória. Atualmente usamos o seguinte código

    System.gc();
    Runtime rt = Runtime.getRuntime();
    long usedMB = (rt.totalMemory() - rt.freeMemory()) / 1024 / 1024;
    logger.information(this, "memory usage" + usedMB);
Este código funciona bem. Isso significa que mostra uma curva de memória que corresponde à realidade. Quando criamos um grande arquivo xml a partir de um DB uma curva sobe, depois que a extração é concluída, ele desce.

alt text

[[[2]] um consultor nos disse que chamar gc() explicitamente é errado, "deixe jvm decidir quando executar gc". Basicamente, os seus argumentos eram: o mesmo que disscussed aqui. Mas ainda não entendo.
    Como posso ter a minha curva de uso da memória?
  • Qual é o problema com o gc explícito()? Eu não me importo com pequenos problemas de desempenho que podem acontecer com GC explícito() e que eu estimaria em 1-3%. O que eu preciso é de memória e monitor thread que me ajuda na análise do nosso sistema no site do cliente.
Author: Community, 2009-06-29

14 answers

Se quiser realmente ver o que se passa na memória VM, deve usar uma boa ferramenta como VisualVM. Este software é livre e é uma ótima maneira de ver o que está acontecendo.

Nada é realmente "errado" com chamadas GC() explícitas. No entanto, lembre-se que quando você chama gc() você está "sugerindo" que o coletor de lixo corra. Não há nenhuma garantia de que ele será executado no momento exato em que você executar esse comando.

 48
Author: amischiefr, 2018-01-20 03:29:04

Existem ferramentas que lhe permitem monitorizar o uso da memória VM. O VM pode expor as estatísticas de memória usando o JMX . Você também pode imprimir as estatísticas do GC para ver como a memória está a funcionar ao longo do tempo.

Sistema De Invocação.gc () pode prejudicar o desempenho do GC porque os objetos serão movidos prematuramente das novas para as velhas gerações, e referências fracas serão apagadas prematuramente. Isso pode resultar em diminuição da eficiência de memória, tempos de GC mais longos, e perda de cache acertos (para caches que usam refs fracos). Concordo com o seu consultor: sistema.gc() é mau. Eu iria tão longe quanto desactivá-lo usando o interruptor da linha de comando.
 28
Author: Mr. Shiny and New 安宇, 2016-02-16 16:27:47
Eu diria que o consultor tem razão na teoria, e você tem razão na prática. Como diz o ditado:
Em teoria, a teoria e a prática são as mesmas. Na prática, não são.
O Java spec diz Esse sistema.o gc sugere chamar a recolha do lixo. Na prática, ele apenas cria um fio e corre imediatamente no Sun JVM. Embora, em teoria, possas estar a estragar uma implementação bem afinada da recolha de lixo da JVM., a menos que esteja a escrever um código genérico destinado a ser implantado em qualquer JVM lá fora, não se preocupe com isso. Se funcionar para ti, fá-lo.
 9
Author: Yishai, 2009-06-29 15:47:58

Pode ver o stagemonitor . É um monitor de desempenho de aplicações java (web) de código aberto. Ele captura métricas de tempo de resposta, métricas JVM, solicitar detalhes (incluindo uma pilha de chamadas capturada pelo analista de Pedidos) e muito mais. A sobrecarga é muito baixa.

Opcionalmente, você pode usar a grafite da base de dados great timeseries com ela para armazenar um longo histórico de pontos de dados que você pode olhar com painéis finos. Exemplo: JVM Memory Dashboard Olha para isto. a página web do projecto para ver imagens, descrições de funcionalidades e documentação.

Nota: eu sou o desenvolvedor do stagemonitor

 9
Author: Felix, 2014-07-30 15:01:50
Espreita o que está a acontecer dentro do tomcat através da VM Visual. http://www.skill-guru.com/blog/2010/10/05/increasing-permgen-size-in-your-server/ alt text

alt text

 6
Author: vsingh, 2010-10-06 21:27:10
Olha para o JVM args. http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#DebuggingOptions

XX:-o PrintGC imprime mensagens na recolha do lixo. Administravel.

-XX:-PrintGCDetails Print more details at garbage collection. Administravel. (Introduzido em 1.4.0.)

-XX:-Impressgctimestamps imprimir datas na recolha do lixo. Fácil de gerir (introduzido em 1.4.0.)

-XX: - PrintTenuringDistribution Imprimir informação sobre a idade.

Embora não vá perturbar o JVM com chamadas explícitas para eles podem não ter o efeito que espera. Para realmente entender o que está acontecendo com a memória em um JVM com Leia qualquer coisa e tudo o que o [[17]}Brian Goetz escreve.
 5
Author: Nick Holt, 2009-06-29 16:03:39

Sistema de execução explícita.gc () em um sistema de produção é uma idéia terrível. Se a memória chegar a qualquer tamanho, todo o sistema pode congelar enquanto um GC completo está em execução. Em um servidor multi-gigabyte, isso pode ser facilmente muito perceptível, dependendo de como o jvm é configurado, e quanto headroom ele tem, etc etc - eu vi pausas de mais de 30 segundos.

Outra questão é que ao chamar explicitamente o GC não está a monitorizar como o JVM está a gerir o GC, você está realmente alterando - dependendo de como você configurou o JVM, ele vai coletar lixo quando apropriado, e geralmente incrementalmente (ele não apenas executar um GC completo quando ele fica sem memória). O que você vai imprimir não será nada como o que o JVM vai fazer por conta própria - para uma coisa você provavelmente vai ver menos GC automáticos / incrementais como você vai estar limpando a memória manualmente.

Como o post de Nick Holt indica, as opções para imprimir a actividade do GC já existem como JVM. bandeira. Pode ter uma linha que imprime gratuitamente e está disponível a intervalos razoáveis, isto vai mostrar-lhe a verdadeira idade.
 5
Author: Steve B., 2009-06-29 16:10:17

Se gosta de uma boa maneira de fazer isto a partir da linha de comando use jstat:

Http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html

Dá informações em bruto a intervalos configuráveis, o que é muito útil para fins de registo e grafagem.

 4
Author: Pablojim, 2009-06-29 20:01:25

Se usar o java 1.5, poderá ver o ManagementFactory.getMemoryMXBean() que lhe dão números em todos os tipos de memória. heap and non-heap, perm-gen.

Um bom exemplo pode ser encontrado lá http://www.freshblurbs.com/explaining-java-lang-outofmemoryerror-permgen-space

 2
Author: Zoukaye, 2009-06-29 15:57:29

Se você usar o JMX desde que o histórico de runs GC você pode usar o mesmo antes/depois dos números, você simplesmente não tem que forçar um GC.

Você só precisa ter em mente que esses GC runs (normalmente um para a antiga e outro para a nova geração) não estão em intervalls regulares, então você precisa extrair a hora de início, bem como para plotar (ou você plotar contra um número de sequência, para propósitos mais práticos que seriam suficientes para plotar).

Por exemplo no Oracle HotSpot VM com ParNewGC, existe um JMX MBean chamado java.lang:type=GarbageCollector,name=PS Scavenge, tem um atributo Lastginfo, devolve um CompositeData da última execução do YG scavenger. É gravado com duration, absoluto startTime e memoryUsageBefore e memoryUsageAfter.

Basta usar um temporizador para ler esse atributo. Sempre que um novo startTime aparece, você sabe que ele descreve um novo evento GC, você extrai a informação de memória e continua pesquisando para a próxima atualização. (Não tenho a certeza se um AttributeChangeNotification de alguma forma pode ser usado.)

Dica: no seu temporizador você pode medir o distância para a última corrida GC, e se isso for muito longo para a resultado de seu plotting, você poderia invocar o sistema.GC () condicionalmente. Mas não o faria num caso OLTP.
 2
Author: eckes, 2012-08-15 19:14:53

Como foi sugerido, tente o VisualVM para obter uma visão básica.

Você também pode usar o Eclipse MAT, para fazer uma análise mais detalhada da memória.

Não faz mal fazer um sistema.gc () desde que você não dependa disso, para a correção do seu programa.
 0
Author: Aakash, 2009-06-29 19:14:54

O problema com o sistema.gc, é que o JVM já atribui automaticamente tempo ao coletor de lixo com base no uso da memória.

No entanto, se você está, por exemplo, trabalhando em uma condição muito limitada de memória, como um dispositivo móvel, sistema.gc permite que você alocar manualmente mais tempo para esta coleta de lixo, mas ao custo do tempo da cpu (mas, como você disse, Você não está muito preocupado com problemas de desempenho da gc).

As melhores práticas seriam provavelmente para apenas usá-lo onde você pode estar fazendo grandes quantidades de desalocação (como limpar um grande array).

Todos considerados, uma vez que você está simplesmente preocupado com o uso da memória, sinta-se à vontade para chamar gc, ou, melhor ainda, ver se faz muita diferença de memória em seu caso, e depois decidir.

 0
Author: bgw, 2009-06-29 22:04:03

Adicionando à lista de respostas, o JConsole (incluído no directório jdk/bin) é também uma boa interface para experimentar.

Referência

 0
Author: Ankit, 2017-04-11 14:01:53