Tamanho do HEAP (-Xms -Xmx)

Como visto em Gerenciamento de memória, o processo Java ao ser executado consome memória de três formas:

    1. Área de Stack: memória que o processo Java utiliza para gerenciar os programas Java que está executando (pilhas de controle e registradores). Também usa memória necessário para que seja executado pelo sistema operacional. O seu tamanho é variável, ou seja, não pode ser fixado, e varia de acordo com o sistema operacional em que é executado e da quantidade e complexidade dos sistemas que a JVM está executando;
    2. Área permanente: é nesta porção de memória que as classes são carregadas. Cada fabricante usa um tamanho default, mas pode ser alterada;
    3. HEAP: Geralmente esta área e a maior das três, pois aqui que o sistema é executado, efetivamente, onde todas as instâncias são criadas e apagadas. Pode ter o seu tamanho fixo ou variável.

O consumo de memória de uma JVM é uma coisa complicada, mas na prática, quando há problemas de memória, elas ocorrem em sua maioria no HEAP, pois é aqui onde ocorre a maior necessidade de memória, onde os objetos são criados e destruídos aos milhares por segundo. Logo, é o local mais suscetível a problemas de memória.

Para um correto gerenciamento de memória, o HEAP conta com dois parâmetros:

    1. Xms: Total de memória inicial, quanto de memória o HEAP terá após a inicialização da JVM;
    2. Xmx: Quantidade máxima de memória que um HEAP pode requerer.

Estes parâmetros são passados em linha de comando. Exemplo: java -server -Xms100m -Xmx1500m <outros parâmetros>...

A memória pode ser definida em Megabytes (m ou M) ou Gigabytes (g u G). Os parâmetros são precedidos por um traço de menos e são sensíveis à letras maiúsculas e minúsculas, devendo ser utilizados como apresentados neste tutorial.

Estratégias de uso

Vale lembra que cada fabricante tem uma particularidade. Quandos os parâmetros são utilizados, eles fazem o que a especificação Java determina que façam. Quando um ou outro parâmetro não está presente, então cada fabricante toma uma decisão. São vários fabricantes e várias versões, pode haver diferenças de comportamento na JVM de um mesmo fabricando, porém de versões diferentes.

Sem parametro algum (na execução da JVM não foram utilizados Xms e Xmx)

Neste caso, o HEAP irá começar com um mínimo de memória e irá aumentando conforme for carregando as classes e criando suas instâncias. Caso a necessidade de memória seja maior que capacidade do sistema operacional em liberá-la para o processo Java, irá ocorrer uma excessão OutOfMemory.

Exemplo: java -server <outros parâmetros>...

Apenas Xms

Será muito semelhante item anterior (não utilização de parâmetros), mas com uma diferença, o HEAP antes de carregar qualquer objeto, irá requerer a quantidade de memória especificado por Xms. Neste caso os objetos serão cirados neste espaço de memória inicial. Caso o sistema que a JVM esteja rodando não utilize muita memória, ele se manterá dentro do valor especificado. Caso o sistema necessite de mais memória que a inicial, estipulado por Xms, ele irá requerer memória da JVM, que irá requisitar ao sistema operacional. O mesmo pode ocorrer, caso não haja memória suficiente e no tempo necessário: OutOfMemory.

Exemplo: java -server -Xms500m <outros parâmetros>...

Xms e Xmx com valores diferentes

A JVM irá iniciar e criar um HEAP do tamanho de Xms, conforme for necessitando de mais memória irá aumentando gradativamente até chegar em Xmx, que é o limite. Este é um limite real, o HEAP não ultrapassa este valor, mesmo que o servidor tenho muita memória livre, só irá utilizar o máximo que foi especificado em Xmx. Caso o HEAP atinja o Xmx e necessite de mais memória, irá disparar o Coletor de lixo (Garbage Collector), que tentará liberar memória que está sendo utilizado por objetos desnecessários. Caso não consiga liberar memória sulficiente veremos a excessão: OutOfMemory.

Exemplo: java -server -Xms500m -Xmx1500m <outros parâmetros>...

Xms igual a Xmx

É muito comum em ambientes de auta performance a utilização de Xms igual a Xmx. Isto ocorre porque quando a JVM necessita de mais memória para o HEAP deve requisitar ao sistema operacional, e isto pode demorar, do ponto de vista computacional, deixando a JVM e tudo que está rodando dentro dela parado. Isto pode causar problemas de lentidão em certos tipos de sistemas. Para evitar o tempo perdido requisitando memória, utilizamos o Xms com o mesm valor que Xms, assim o HEAP inicia com o seu tamanho máximo. Evitando perder tempo pedindo mais memória.

Exemplo: java -server -Xms2500m -Xmx2500m <outros parâmetros>...