Pergunta

Como encontrar um vazamento de memória em Java (usando, por exemplo, JHat)?Eu tentei carregar o despejo de pilha em JHat para dar uma aparência básica.No entanto, eu não entendo como eu sou suposto ser capaz de encontrar a raiz de referência (ref) ou o que ele é chamado.Basicamente, eu posso dizer que há várias centenas de megabytes de hash tabela de entradas ([java.util.HashMap$Entrada ou algo assim), mas os mapas são utilizados em todo o lugar...Existe alguma maneira de pesquisar para mapas grandes, ou talvez encontrar-geral raízes do objeto de grandes árvores?

[Editar] Ok, eu li as respostas até agora, mas vamos apenas dizer que eu sou um barato safado (ou seja, eu estou mais interessado em aprender a usar o JHat que pagar para JProfiler).Também, JHat está sempre disponível, pois faz parte do JDK.A menos, claro, não há nenhuma maneira com JHat mas a força bruta, mas eu não posso acreditar que pode ser o caso.

Também, eu não acho que vai ser capaz de realmente modificar (adicionando o log de todos mapa tamanhos) e executá-lo por tempo suficiente para me repare o vazamento.

Foi útil?

Solução

Eu uso o seguinte abordagem para encontrar vazamentos de memória em Java.Eu usei jProfiler com grande sucesso, mas eu acredito que qualquer ferramenta especializada, com capacidades de gráficos (diffs são mais fáceis de analisar, de forma gráfica) irá funcionar.

  1. Inicie o aplicativo e aguarde até ele chegar ao "estável" o estado, quando todos a inicialização é concluída e o aplicativo estiver ocioso.
  2. Executar a operação suspeita de produzir um vazamento de memória várias vezes para permitir que qualquer um cache de banco de dados relacionados com a inicialização ocorra.
  3. Execute o GC e tirar instantâneo de memória.
  4. Executar a operação novamente.Dependendo da complexidade da operação e tamanhos de dados que é processado operação poderá ser necessário executar várias vezes.
  5. Execute o GC e tirar instantâneo de memória.
  6. Executar um diff para 2 instantâneos e analisá-lo.

Basicamente, a análise deve começar a partir de positivo maior de comparação, por exemplo, tipos de objetos e encontre o que faz com que os objetos extras para o stick de memória.

Para aplicativos da web a processar pedidos em vários segmentos de análise torna-se mais complicado, mas, no entanto abordagem geral ainda se aplica.

Eu fiz um grande número de projectos especificamente destinadas a reduzir o consumo de memória dos aplicativos e esta abordagem geral com algum aplicativo específico ajustes e truque sempre funcionou bem.

Outras dicas

Questionador aqui, eu tenho a dizer a obtenção de uma ferramenta que não demorou 5 minutos para responder a quaisquer clique em torna-lo muito mais fácil para encontrar possíveis vazamentos de memória.

Pois as pessoas estão sugerindo várias ferramentas ( só testei o visual do wm desde que eu tenho de que o JDK e JProbe julgamento ) eu pensei que eu deveria sugerir um livre / open source ferramenta construída sobre a plataforma Eclipse, o Analisador de Memória (por vezes referido como o SAP analisador de memória) disponível em http://www.eclipse.org/mat/ .

O que é realmente legal sobre esta ferramenta, é que ela indexado de informação de pilha quando, pela primeira vez aberto, o que permitiu isso para mostrar dados como mantidos pilha sem esperar 5 minutos para cada objeto (praticamente todas as operações foram muito mais rápido do que as outras ferramentas que eu tentei).

Quando você abrir o despejo, a primeira tela que mostra um gráfico de pizza com os maiores objetos (contagem mantida de pilha) e pode-se navegar rapidamente para baixo, para os objetos que são, para grande conforto.Ele também tem uma localização provável fuga de suspeitos que eu reccon pode vir a calhar, mas desde que a navegação era o suficiente para mim, eu realmente não chegar a ele.

Uma ferramenta é uma grande ajuda.

No entanto, há momentos em que você não pode usar uma ferramenta:o despejo de pilha é tão grande que falha a ferramenta, você está tentando solucionar problemas de uma máquina em algum ambiente de produção para o qual você só tem acesso a shell, etc.

Nesse caso, ele ajuda a saber o caminho de volta a hprof arquivo de despejo.

Procure SITES de COMEÇAR.Isso mostra que os objectos que estão a utilizar mais memória.Mas os objetos não são agrupados exclusivamente por tipo:cada entrada inclui também um "traço" de IDENTIFICAÇÃO.Em seguida, você pode pesquisar para que o "RASTREIO nnnn" para ver o topo de alguns frames da pilha onde o objeto foi alocado.Muitas vezes, depois de eu ver onde o objeto é alocado, eu encontrar um bug e eu sou feito.Além disso, observe que você pode controlar quantos quadros são gravados na pilha com as opções de para -Xrunhprof.

Se você verificar a alocação de site, e não vê nada de errado, você tem que começar para trás o encadeamento de alguns desses objetos vivos para objetos raiz, para encontrar o inesperado cadeia de referência.Esta é uma ferramenta realmente ajuda, mas você pode fazer a mesma coisa com a mão (bem, com grep).Não é apenas um objeto raiz (isto é, o objeto não sujeitos a coleta de lixo).Segmentos, classes, e de quadros de pilha atuar como objetos raiz, e tudo o que eles fazem referência fortemente não é colecionável.

Para fazer o encadeamento, olhar no DESPEJO de PILHA seção de entradas com o mau identificação de rastreamento.Isso vai levar você para um OBJ ou ARR entrada, que mostra um identificador de objeto exclusivo em hexadecimal.Procurar todas as ocorrências de que o id de achar que tem uma forte referência para o objeto.Siga cada um desses caminhos para trás como eles galho até você descobrir de onde o vazamento está.Veja por que uma ferramenta tão útil?

Membros estáticos são um reincidente por vazamentos de memória.Na verdade, mesmo sem uma ferramenta, seria a pena gastar alguns minutos olhando através de seu código para o Mapa estático membros.Pode um mapa crescer grande?Faz alguma coisa de sempre limpar suas entradas?

A maior parte do tempo, em aplicações enterprise Java heap dado é maior do que o tamanho ideal do máximo de 12 a 16 GB.Eu achei difícil fazer o NetBeans profiler trabalhar diretamente sobre estes grandes aplicativos java.

Mas normalmente isso não é necessário.Você pode usar o jmap utilitário que vem com o jdk para tomar um "ao vivo" despejo de pilha , que é jmap vai despejo de pilha após a execução do GC.Fazer alguma operação sobre a aplicação, espere até a operação é concluída, em seguida, tomar o outro "ao vivo" despejo de pilha.Use ferramentas como Eclipse ESTEIRA para carregar o heapdumps, ordenar o histograma, consulte os objectos que têm aumentado, ou que são os mais altos, Isso daria uma pista.

su  proceeuser
/bin/jmap -dump:live,format=b,file=/tmp/2930javaheap.hrpof 2930(pid of process)

Só há um problema com essa abordagem;Enorme pilha de despejos, mesmo com a opção, podem ser grandes demais para transfer out para o desenvolvimento de volta, e pode precisar de uma máquina com bastante memória/RAM para abrir.

Que é onde a classe do histograma vem em foto.Você pode despejar um live classe do histograma com o jmap ferramenta.Isso vai lhe dar apenas a classe do histograma de uso de memória.Basicamente, ele não terá as informações para a cadeia de referência.Por exemplo, pode colocar array de char no topo.E a classe String em algum lugar abaixo.Você tem que desenhar a conexão de si mesmo.

jdk/jdk1.6.0_38/bin/jmap -histo:live 60030 > /tmp/60030istolive1330.txt

Em vez de tomar dois heap dumps, tomar duas classe de histogramas, assim como o descrito acima;Em seguida, compare a classe de histogramas e ver as classes que estão a aumentar.Veja se você pode se relacionar com as classes Java para o seu aplicativo de classes.Isso vai dar uma boa dica.Aqui é um pythons script que pode ajudá-lo a comparar dois jmap histograma despejos. histogramparser.py

Finalmente ferramentas como JConolse e VisualVm são essenciais para ver a memória de crescimento ao longo do tempo, e ver se há um vazamento de memória.Finalmente, às vezes, o problema não pode ser uma fuga de memória , mas o uso de memória alta.Para isso ativar o GC, log;usar um mais avançado e novo compactação GC como G1GC;e você pode usar o jdk ferramentas como jstat para ver o GC comportamento ao vivo

jstat -gccause pid <optional time interval>

Outros referecences para o google -jhat, jmap, Cheio de GC, Humongous de alocação, G1GC

Existem ferramentas que devem ajudar você a encontrar o seu vazamento, como JProbe, YourKit, AD4J ou JRockit Mission Control.O último é o que eu, pessoalmente, saber melhor.Qualquer boa ferramenta deve permitir a broca para baixo para um nível onde você pode facilmente identificar o que vazamentos, e de onde o vazamento de objetos são alocados.

Utilizando tabelas de hash, Hashmaps ou similares é uma das poucas maneiras que você pode faz vazamento de memória em Java em tudo.Se eu tivesse que encontrar a fuga pelo lado eu iria peridically imprimir o tamanho do meu HashMaps, e a partir daí encontrar aquele onde eu adicionar itens e se esqueça de apagá-las.

Bem, há sempre o low tech solução de adição de log do tamanho de seus mapas quando você modificá-los, em seguida, procurar os registos para os quais mapas estão a crescer além de um tamanho razoável.

O NetBeans tem um built-in profiler.

Você realmente precisa usar uma memória profiler faixas atribuições.Dê uma olhada no JProfiler - seus "walker" recurso é grande, e eles têm integração com todos os principais IDEs Java.Não é de graça, mas não é que o cara quer (us$499 para uma única licença) - você vai queimar de 500 $a pena de tempo muito rapidamente, lutando para encontrar uma fuga com menos de ferramentas sofisticadas.

você pode querer verificar para fora o jconsole.Ele também faz parte do JDK e descobri que isso é útil para encontrar memória/vazamentos de referência em conjunto com jhat.Também dê uma olhada no este entrada de blog.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top