domingo, 17 de fevereiro de 2013

JVM alguns segredos sobre o seu sombrio mundo


Introdução


Java Virtual Machine (JVM) como o próprio nome sugere é um computador virtual que reside em um computador real. A JVM da uma flexibilidade plataforma.

Os códigos Java possuem atributos e métodos, objetos, etc. Quando o compilamos gera um arquivo de bytecode e interpretado pela JVM e executa o programa de forma que realiza o que lhe foi escrito.



É interessante conhecermos seu funcionamento interno é essencial para qualquer aplicação Java. Muitas vezes, deixamos de lado ajustes importantes de Garbage Collector (GC), não entendemos as implicações do JIT no nosso design ou enfrentarmos problemas práticos com ClassLoaders.

GC


Uma das maiores dificuldades na hora de programar era o gerenciamento de memoria. Os desenvolvedores são os responsáveis pela sua locação e liberação manualmente, o que levava muitos erros de memoria.

O GC é um dos principais componentes da JVM e responsável pela liberação da memoria que não esteja sendo mais utilizada.
Quando a aplicação libera todas as referencias para algum objeto, este passa a ser considerado lixo e pode ser coletado pela GC a qualquer momento. Conseguimos determinar este momento de coleta de lixo pela GC? Não.

Esta base é conhecida como algoritmo GC Mark-And-Sweep, constituído em duas fases, na primeira percorre a memoria e marca todos os objetos acessíveis pelas threads atuais e a segunda que varre (sweep) novamente a memoria e coleta os objetos.

Geralmente 95% dos objetos criados durante a execução de alguma aplicação tem vida extremamente curta, isto é, são rapidamente descartados. É o chamamos de alto índice de mortalidade entre os objetos.

Mesmo métodos curtos e simples, como o toString, acabam gerando objetos intermediários que rapidamente não serão mais referenciados. A memoria é dividida em duas partes: YOUNG GENERATION e OLD GENERATION.

Novos objetos são alocados na YOUNG e, assim que ela estiver lotada, é efetuado o chamado minor collect. É neste passo que os objetos sobreviventes são copiados para a OLD, e todo o espaço da YOUNG torna-se disponível novamente para alocação.

Um mito muito comum na comunidade Java é de que se criarmos N objetos o GC irá passar para o processo de PERMGEN e não é verdade. Na verdade, como os algoritmos mal estruturados podem dar N voltas e afetar o processo da GC, assim levando o mesmo a executar o PERMGEN, nem passando para o processo OLD e desta forma levando ao estouro de memoria.




O gerenciamento da memória JVM


A área total usada para armazenar os objetos na JVM é conhecido como Heap. O tamanho que será dado a memória Heap é controlado pelas opções -Xms e -Xmx. A primeira opção é para determinar o tamanho inicial da Heap e o segundo para determinar o tamanho máximo de memória consumida.
Inicialmente o sistema operacional aloca o total de memória dada pelo comando -Xms e este valor não será devolvido enquanto a JVM estiver ativa.

Os problemas na maioria das vezes é arquitetura mal elaborada que cria classes em números exagerado, algoritmos que executam vários círculos e gera N vezes iterações desnecessários e consultas a bancos que carregam milhões de dados na memória. Este é o momento que ocorre, chamado de stack OutOfMemoryError, onde milhares de aplicações ocorrem este tipo de problema por não conhecerem a arquitetura da JVM.

Conclusão


Saiba adequar sua aplicação à hipóteses das gerações, seja adequando seu código, seja conhecendo as melhores configurações de execução da sua JVM.



Bibliografia


Livro Arquitetura e Design de Software - pág 26 - Ano 2009

Nenhum comentário:

Postar um comentário