Como fazer o perfil de memória em Java?
basicamente o que eu quero saber é qual variável (e espero que mais detalhes como em que método) toda a memória está a ser usada para que eu pode concentrar-se em trabalhar lá. Há uma maneira fácil de fazer isto? Eu agora estou usando eclipse e java para desenvolver (e instalado visualVM e netbeans especificamente para o perfil, mas estou disposto a instalar qualquer outra coisa que você sente faz este trabalho feito).
EDIT: idealmente, estou à procura de algo que pegue em todos os meus objectos e os separe por tamanho(para que possa ver qual deles está a monopolizar a memória). Actualmente devolve informações genéricas como string [] ou int [], mas eu quero saber qual o objecto está a referir-se para que eu possa trabalhar para que o seu tamanho seja mais optimizado.
5 answers
As cadeias de caracteres são problemáticas
Basicamente em Java, String
as referências (coisas que usam char[]
nos bastidores ) dominarão a maioria dos negócios aplicações de memória. A forma como são criados determina a quantidade de memória que consomem na JVM.
Uma vez, ao traçar o perfil da utilização do CPU numa aplicação web que também tinha uma dependência do Oracle JDBC, descobri que StringBuffer.append()
dominava os ciclos do CPU por muitas ordens de magnitude sobre todas as outras chamadas de método combinadas, muito menos qualquer outra chamada de método único. O motorista do JDBC fez muitas e muitas coisas. de manipulação, uma espécie de troca de usar PreparedStatements
para tudo.
O que você está preocupado com você não pode controlar, não diretamente de qualquer maneira
O que você deve focar é o que em seu controle, que é certificar-se de que você não mantém referências por mais tempo do que você precisa, e que você não está duplicando as coisas desnecessariamente. As rotinas de coleta de lixo em Java são altamente otimizadas, e se você aprender como seus algoritmos funcionam, você pode ter certeza de que o seu o programa se comporta da maneira ideal para que esses algoritmos funcionem.
Java Heap Memory não é como a memória gerenciada manualmente em outras linguagens, essas regras não se aplicam
O que são considerados fugas de memória noutras línguas não são a mesma coisa/causa raiz como em Java com o seu sistema de recolha de lixo.
O mais provável é que na memória Java não seja consumida por um único objeto uber que está vazando ( referência balançando em outros ambientes ).
([19]} é muito provável que haja lotes de dotações mais pequenas por causa deStringBuffer
/StringBuilder
Os objectos não dimensionados de forma apropriada nas primeiras instantâneas e que, em seguida, têm de crescer automaticamente as matrizes char[]
para manter as chamadas subsequentes append()
.
Estes objetos intermediários podem ser mantidos por mais tempo do que o esperado pelo coletor de lixo por causa do escopo em que eles estão e muitas outras coisas que podem variar em tempo de execução.
Exemplo: o coletor de lixo pode decidir que lá são candidatos, mas porque ele considera que há muita memória ainda a ser tido que pode ser muito caro tempo sábio para puxá-los para fora nesse ponto no tempo, e ele vai esperar até que a pressão da memória fica maior.
O coletor de lixo é muito bom agora, mas não é magia, se você está fazendo coisas degeneradas, isso fará com que ele não funcione de forma otimista. Há muita documentação na internet sobre as configurações do coletor de lixo para todas as versões do JVMs.Estes objectos não referenciados podem simplesmente não ter atingido o momento em que o coletor de lixo pensa que precisa deles para que eles sejam apagados da memória, ou pode haver referências a eles mantidos por algum outro objeto ( List
) por exemplo, que você não percebe ainda pontos para esse objeto. Isto é o que é mais comumente referido como um vazamento em Java, que é um vazamento de referência mais especificamente.
Exemplo: se sabe que precisa de construir um 4K String
usando um StringBuilder
crie - o com new StringBuilder(4096);
não o padrão, que é como 32 e irá imediatamente começar a criar lixo que pode representar muitas vezes o que você acha que o objeto deve ser tamanho sábio.
Você pode descobrir quantos tipos de objetos estão instanciados com VisualVM, isso lhe dirá o que você precisa saber. Não vai haver uma grande luz piscando que aponta para uma única instância de uma única classe que diz: "Este é o grande consumidor de memória!", isto é, a menos que existe apenas uma instância de alguns char[]
em que você está lendo algum arquivo massivo, e isso também não é possível, porque muitas outras classes usam char[]
internamente; e então você praticamente já sabia disso.
Não vejo nenhuma menção OutOfMemoryError
OutOfMemoryError
. Isto não é C, C++, Objective-C, ou qualquer outra linguagem de gerenciamento de memória manual / tempo de execução. Você não pode decidir o que está na memória ou não no nível de detalhe que você está esperando que você deve ser capaz de.
InJProfiler , você pode ir para o heap walker e ativar a maior vista de objetos. Você vai ver os objetos a reter mais memória. Memória "retida" é a memória que seria libertada pelo coletor de lixo se você removesse o objeto.
Você pode então abrir os nós de objetos para ver a árvore de referência dos objetos retidos. Aqui está uma imagem da maior vista de objectos:
AVISO: A minha empresa desenvolve a JProfiler
Eu recomendaria capturar lixeiras de heap e usar uma ferramenta comoEclipse MAT que te permite analisá-las. Existem muitos tutoriais disponíveis. Ele fornece uma visão da árvore Dominadora para fornecer uma visão sobre as relações entre os objetos no heap. Especificamente para o que você mencionou, a característica" path to GC roots " do MAT irá dizer-lhe onde a maioria desses objetos char [], String[] e int[] estão sendo referenciados. A JVisualVM também pode ser útil na identificação de vazamentos e alocações, particularmente usando instantâneos com traces de pilha de alocação. Existem alguns passos do processo {[[3]} de obter os instantâneos e compará-los para encontrar o ponto de alocação.
Java JDK vem com JVisualVM sob a pasta bin, logo que o seu servidor de aplicações (por exemplo, esteja a correr), você poderá executar o visualvm e ligá-lo ao seu localhost, que lhe irá fornecer a alocação de memória e permitir-lhe-á executar o heap dump
Para mais detalhes sobre como activar: http://sysdotoutdotprint.com/technologies/java/6
Se usar o visualVM para verificar o seu uso de memória, ele centra-se nos dados, não nos métodos. Talvez os seus grandes dados de char sejam causados por muitos valores de String? A menos que você esteja usando recursão, os dados não serão de variáveis locais. Então você pode se concentrar nos métodos que insiram elementos em grandes estruturas de dados. Para descobrir que afirmações precisas causam a sua "fuga de memória", sugiro-lhe adicionalmente {[[2]}
- Leia o item Java eficaz de Josh Bloch 6: (eliminar objecto obsoleto Referências)
- use uma estrutura de Registo uma criação de instância de registo no nível de verbosidade mais elevado.