Vazamento de memória possível no número das classes carregadas em Java Application

StackOverflow https://stackoverflow.com/questions/167740

  •  03-07-2019
  •  | 
  •  

Pergunta

Eu recentemente começou a perfilar uma aplicação java osgi que estou escrevendo usando VisualVM. Uma coisa que tenho notado é que quando o aplicativo começa a enviar dados para um cliente (mais de JMS), o número de classes carregadas começa a aumentar a um ritmo constante. O tamanho da pilha e do tamanho PermGen permanece constante, no entanto. O número de classes nunca cai, mesmo depois que ele pára de enviar dados. É este um vazamento de memória? Eu acho que é, porque as classes carregadas devem ser armazenados em algum lugar, no entanto, a pilha e permgen não aumentar mesmo depois que eu executar o aplicativo por várias horas.

Para o screenshot do meu aplicativo de perfil ir aqui

Foi útil?

Solução

Você está criando dinamicamente novas classes na mosca de alguma forma?

Obrigado por sua ajuda. Eu descobri o que é o problema. Em uma das minhas aulas, eu estava usando JAXB para criar uma cadeia de caracteres XML. Ao fazer isso, JAXB ueses reflexão para criar uma nova classe.

JAXBContext context = JAXBContext.newInstance(this.getClass());

Assim, embora a JAXBContext não estava dizendo ao redor do monte, as aulas tinham sido carregados.

Eu tenho que correr o meu programa novamente, e eu vejo um patamar normal, como seria de esperar.

Outras dicas

Eu estou disposto a apostar que o problema está relacionado à geração de bytecode.

Muitas bibliotecas usar CGLIB, BCEL, Javasist ou Janino para gerar bytecode para novas classes em tempo de execução e, em seguida, carregá-los de carregador de classe controlada. A única maneira de liberar essas classes é liberar todas as referências para o carregador de classe.

Uma vez que o carregador de classe é realizada por cada classe, isso também significa que você não deve liberar as referências a todas as classes, bem [1]. Você pode pegar estes com um profiler decente (eu uso YourKit - busca de várias instâncias carregador de classe com o mesmo tamanho retidos)

Um problema é que a JVM não descarrega aulas por padrão (a razão é compatibilidade com versões anteriores - que as pessoas assumem (erradamente) que inicializadores estáticos seria executado apenas uma vez A verdade é que eles são executados cada vez que uma classe é carregada. .) Para habilitar o descarregamento, você deve passar algum uso as seguintes opções:

-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled

(testado com JDK 1.5)

Mesmo assim, a geração de bytecode excessivo não é uma boa idéia, então eu sugiro que você olhar em seu código para encontrar o culpado e cache as classes geradas. infratores frequentes são linguagens de script, proxies dinâmicos (incluindo os gerados por servidores de aplicativos) ou modelo enorme Hibernate (neste caso, você pode simplesmente aumentar o seu permgen).

Veja também:

  1. http://blogs.oracle.com/watt/resource /jvm-options-list.html
  2. http://blogs.oracle.com/jonthecollector/entry/presenting_the_permanent_generation
  3. http://forums.sun.com/thread.jspa?messageID=2833028

Você pode encontrar algumas bandeiras hotspot para ser de uso para entender este comportamento como:

  • -XX: + TraceClassLoading
  • -XX: + TraceClassUnloading

Esta é uma boa referência:

http://java.sun.com/javase/technologies/hotspot /vmoptions.jsp

A menos que eu entenda mal, nós estamos olhando aqui no classes carregadas, não instâncias.

Quando seu código primeiras referências a classe, a JVM tem o ClassLoader sair e buscar as informações sobre a classe de um arquivo .class ou similar.

Não tenho certeza em que condições seria descarregar uma classe. Certamente ele nunca deve descarregar qualquer classe com informações estáticas.

Assim, gostaria de esperar um padrão mais ou menos como a sua, onde, como seu aplicativo é executado ele vai para áreas e referências novas classes, de modo que o número de classes carregadas que ir para cima e para cima.

No entanto, duas coisas parece estranho para mim:

  1. Por que é tão linear?
  2. Por que não Plateau?

Eu esperaria que a tendência para cima, mas em uma linha vacilante, e depois estabilizarem a aumentar como a JVM já carregado a maioria das classes suas referências do programa. Quer dizer, há um número finito de aulas referenciados na maioria das aplicações.

Você está criando dinamicamente novas classes na mosca de alguma forma?

Gostaria de sugerir a execução de um aplicativo de teste simples através do mesmo depurador para obter um caso base. Então você poderia considerar a implementação de seu próprio ClassLoader que cospe alguma informação de depuração, ou talvez há uma ferramenta para torná-lo relatar.

Você precisa descobrir o que essas classes que estão sendo carregadas são.

Sim, é geralmente um vazamento de memória (uma vez que nós realmente não lidar diretamente com a memória, é mais de uma instância de vazamento de classe). Eu já passei por este processo antes e, geralmente, é algum ouvinte adicionado a um conjunto de ferramentas de idade que não removê-lo eu.

No código antigo, um relacionamento ouvinte faz com que o objeto "ouvinte" permanecer ao redor. Eu olhava para toolkits mais velhas ou aqueles que não passaram por muitas rotações. Qualquer execução biblioteca de longa existente em um JDK mais tarde viria a saber sobre objetos de referência que retira a exigência de "Remover Listener".

Além disso, chamada dispor em suas janelas se você recriá-los cada vez. Eu não acho que eles nunca vão embora se você não (Na verdade, há também um descarte no ambiente próximo).

Não se preocupe com Swing ou ouvintes JDK, eles devem todas as referências de uso para que você deve estar bem.

Use a Eclipse Memória Analyzer para verificar se há aulas duplicados e vazamentos de memória. Pode acontecer que a mesma classe é carregado mais de uma vez.

Saudações, Markus

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