Otimizando o Desempenho de Aplicações Java

JavaBeginner
Pratique Agora

Introdução

Os parâmetros da JVM são usados para configurar a Java Virtual Machine (JVM), responsável pela execução do bytecode Java. Ao configurar corretamente esses parâmetros, podemos melhorar o desempenho das aplicações Java. Neste laboratório, aprenderemos como definir alguns parâmetros da JVM comumente usados para otimizar o desempenho de aplicações Java.

Configurando a Memória Heap

A memória heap é a área de dados em tempo de execução onde os objetos Java são alocados. Podemos definir o tamanho da memória heap com os parâmetros -Xmx e -Xms.

  • -Xmx<heap size>[unit]: define o tamanho máximo da heap.
  • -Xms<heap size>[unit]: define o tamanho inicial da heap.

Por exemplo, para definir o tamanho mínimo da heap como 512MB e o tamanho máximo como 1GB, podemos usar o seguinte comando:

java -Xms512m -Xmx1g MyApp

Escolhendo Coletores de Lixo (Garbage Collectors)

A coleta de lixo (Garbage Collection) é o processo de liberar memória ocupada por objetos que não estão mais sendo usados pela aplicação Java. A escolha do coletor de lixo pode ter um impacto significativo no desempenho da aplicação. A JVM oferece vários coletores de lixo, cada um com seus próprios pontos fortes e fracos.

  • -XX:+UseSerialGC: habilita o coletor de lixo serial, que usa uma única thread para a coleta.
  • -XX:+UseParallelGC: habilita o coletor de lixo paralelo, que usa múltiplas threads para a coleta.
  • -XX:+UseParNewGC: habilita o coletor de lixo concurrent-mark-sweep (CMS), que usa múltiplas threads para realizar a coleta de lixo de forma concorrente.
  • -XX:+UseG1GC: habilita o coletor de lixo Garbage-first (G1), projetado para fornecer tempos de pausa consistentes e alto rendimento.

Por exemplo, para habilitar o coletor de lixo paralelo, podemos usar o seguinte comando:

java -XX:+UseParallelGC MyApp

Registrando Atividades de Coleta de Lixo

O registro (log) da coleta de lixo nos permite monitorar o desempenho do coletor e ajustar seus parâmetros com base nos requisitos da aplicação. Podemos usar os seguintes parâmetros para habilitar o log da coleta de lixo:

  • -Xlog:gc*: habilita o log da coleta de lixo em versões modernas do Java.
  • file=gc.log: grava a saída do log em um arquivo chamado gc.log.
  • filecount=10: mantém até 10 arquivos de log rotacionados.
  • filesize=10M: rotaciona o arquivo de log após atingir 10 MB.

Por exemplo, para habilitar o log da coleta de lixo e armazená-lo em gc.log, podemos usar o seguinte comando:

java -Xlog:gc*:file=gc.log:time,uptime,level,tags:filecount=10,filesize=10M MyApp

Tratamento de Erros de Memória Insuficiente (Out of Memory)

Quando a JVM fica sem memória, ela lança um erro do tipo Out Of Memory. Podemos usar os seguintes parâmetros da JVM para lidar com esse erro:

  • -XX:+HeapDumpOnOutOfMemoryError: quando o erro de memória insuficiente ocorre, a JVM gravará um dump da heap em disco.
  • -XX:HeapDumpPath=<path to heap dump file>: especifica o caminho para o arquivo de dump da heap.
  • -XX:OnOutOfMemoryError=<command>: quando o erro de memória insuficiente ocorre, a JVM executará o comando especificado.
  • -XX:+UseGCOverheadLimit: a JVM usa esta opção para definir um limite na quantidade de tempo gasto na coleta de lixo.

Por exemplo, para configurar a JVM para gravar um dump da heap no arquivo /path/to/heapdump.hprof quando ocorrer um erro de memória insuficiente, podemos usar o seguinte comando:

java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/heapdump.hprof MyApp

Usando JVM de 64 bits

Podemos usar o parâmetro -d para selecionar a JVM de 32 bits ou 64 bits. Por exemplo, para usar a JVM de 64 bits, podemos usar o seguinte comando:

java -d64 MyApp

Compilando e Executando Aplicação Java com Parâmetros da JVM

Vamos usar o programa HelloWorld.java para compilar e executar a aplicação Java com os parâmetros da JVM que aprendemos nos passos anteriores.

cd ~/project
touch HelloWorld.java

Insira o seguinte código:

class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

Salve o arquivo e saia. Agora, vamos compilar e executar o código com o parâmetro -Xmx:

javac HelloWorld.java
java -Xmx512m HelloWorld

Isso define o tamanho máximo da heap como 512MB. Devemos ver a saída:

Hello, World!

Compilando e Executando Aplicação Java com Coletores de Lixo

Agora, vamos compilar e executar a aplicação Java com o coletor de lixo paralelo:

java -XX:+UseParallelGC HelloWorld

Devemos ver a saída:

Hello, World!

Compilando e Executando Aplicação Java com Log de Coleta de Lixo

Agora, vamos compilar e executar a aplicação Java com o log da coleta de lixo habilitado:

java -Xlog:gc*:file=gc.log:time,uptime,level,tags:filecount=10,filesize=10M HelloWorld

Isso grava os logs da coleta de lixo em gc.log no diretório atual enquanto o programa é executado.

Compilando e Executando Aplicação Java com Outros Parâmetros Frequentes

Agora, vamos compilar e executar a aplicação Java com os parâmetros -XX:+UseStringDeduplication e -XX:MaxHeapFreeRatio:

java -XX:+UseStringDeduplication -XX:MaxHeapFreeRatio=70 HelloWorld

Isso habilita a deduplicação de strings e define a proporção máxima de espaço livre na heap após a coleta de lixo para 70%.

Resumo

Neste laboratório, aprendemos como definir vários parâmetros da JVM para otimizar o desempenho de aplicações Java. Aprendemos como definir o tamanho da memória heap, escolher coletores de lixo, habilitar o log da coleta de lixo, lidar com erros de memória insuficiente (Out Of Memory), usar a JVM de 64 bits e definir outros parâmetros usados frequentemente. Também aprendemos como compilar e executar uma aplicação Java com parâmetros da JVM.