Skip to content

Instantly share code, notes, and snippets.

@rponte
Last active June 4, 2022 01:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rponte/5ad3689e7cc57796a775db825c94b9ca to your computer and use it in GitHub Desktop.
Save rponte/5ad3689e7cc57796a775db825c94b9ca to your computer and use it in GitHub Desktop.
Conhecendo e setando parâmetros da JVM

Conhecendo e setando parâmetros da JVM

Material de suporte rápido para conhecer e setar parâmetros de JVM mais comuns relacionados a propriedades da JVM, configuração de frameworks e libs, aplicação e tuning de memória heap e metaspace, além da definição do algoritimo de GC e algumas configurações para troubleshooting.

Introdução

Todos os comandos aqui são executados via linha de comando, mas podem ser definidos na sua IDE, variável de ambiente (JAVA_OPTS) ou no seu servidor de integração contínua (CI).

Rodando uma aplicação (jar):

java -jar app.jar

Rodando uma aplicação com argumentos de aplicação:

java -jar calculadora.jar "somar" 1 2    # resultado=3

Passando propriedades de JVM para aplicação:

java -Duser.timezone=America/Sao_Paulo -jar app.jar    # novo fuso horário: São Paulo

Passando propriedades especificas de frameworks para aplicação:

java -Dserver.port=8083 -jar app.jar     # porta do servidor web no Spring Boot 2.x

Passando propriedades especificas de negócio para aplicação:

java -Dhabilita.logs=true -jar app.jar   # propriedade "habilita.logs" será utilizada pela app

Memória

Executando uma aplicação Java sem informar parâmetros de memória:

java -jar app.jar      # tuning de memória baseado na máquina 

Ao executar uma aplicação Java sem informar parâmetros de memória, a JVM vai fazer o self-tuning de acordo com as configurações da máquina (ou container) hospedeira. Ou seja, a JVM vai olhar para CPU, quantidade de cores, RAM da máquina, arquitetura 32 ou 64bits etc para só então definir a quantidade de memória para Heap, Metaspace etc. Essa feature é conhecida como Ergonomics.

Passando parâmetros de memória Heap da JVM para aplicação via linha de comando:

java -Xms256m -Xmx512m -jar app.jar      # heap.inicial=256mb; heap.maxima=512mb 

Passando parâmetros de memória Metaspace da JVM para aplicação via linha de comando:

java -XX:MaxMetaspaceSize=2048m -jar app.jar  # metaspace.maxima=2gb

Passando parâmetros de memória da JVM para aplicação via linha de comando:

java -Xms256m -Xmx512m -XX:MaxMetaspaceSize=2048m -jar app.jar

GC - Garbage Collector

Definindo o algoritimo de GC utilizado pela JVM:

java -jar app.jar                          # usa GC default do java
java -XX:+UseG1GC -jar app.jar             # G1 eh default a partir do java 9
java -XX:+UseParallelGC -jar app.jar       # Parallel GC eh default no java 8
java -XX:+UseZGC -jar app.jar              # define Z GC na JVM

Habilitando os logs do GC (pouco overhead e útil para troubleshooting em produção):

java -Xlog:gc*:file=/var/log/app-gc.log -jar app.jar

Você pode importar o arquivo de log app-gc.log gerado em ferramentas de analise como GCEasy para entender exatamente o comportamento do GC, uso da memória heap e metaspace, possíveis vazamentos de memória e muitos mais.

Troubleshooting

Gerando heap dump em caso de OutOfMemoryError:

java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./var/dumps/heapdump-app.hprof -jar app.jar

Ao ocorrer um OutOfMemoryError a JVM vai gerar um arquivo com o snapshot da heap no momento do erro. O arquivo heapdump-app.hprof será criado no diretório /var/dumps. A ideia é importar este arquivo em alguma ferramenta ou serviço de analise de heap dump como VisualVM ou Eclipse MAT.

Gerando GC Logs durante toda a atividade da JVM (o overhead é minimo e deveria ser habilitado em produção):

java -Xlog:gc*:file=./var/gc/app-logs.gc -jar app.jar

A JVM vai gerar um ou mais arquivos com os logs do GC (métricas, eventos de coleta, tipos de coleta, tempo de cada coleta etc). O arquivo app-logs.gc será criado no diretório /var/gc. A ideia é importar este arquivo em alguma ferramenta ou serviço de analise de GC Logs, como GC Viewer ou GCEasy.

Terminando a aplicação em caso de OutOfMemoryError:

java -XX:+ExitOnOutOfMemoryError -jar app.jar

Terminando a aplicação com mensagem de erro de crash em caso de OutOfMemoryError:

java -XX:+CrashOnOutOfMemoryError -jar app.jar

Aqui seria um exemplo de erro gerado na saída padrão:

 Aborting due to java.lang.OutOfMemoryError: GC overhead limit exceeded
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (debug.cpp:308), pid=26064, tid=0x0000000000004f4c
#  fatal error: OutOfMemory encountered: GC overhead limit exceeded
#
# JRE version: Java(TM) SE Runtime Environment (8.0_181-b13) (build 1.8.0_181-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode windows-amd64 compressed oops)
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\workspace\rafael.ponte\trunk\buggyapp\hs_err_pid26064.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#

Da mensagem acima, você pode observar o arquivo de log hs_err_pid26064.log gerado no caminho C:\workspace\rafael.ponte\trunk\buggyapp\hs_err_pid26064.log. Esse arquivo de core dump possui informações sobre o crash. Você pode usar ferramentas para analisar o log, como FastThread e VisualVM, mas a maior parte das informações presentes no arquivo de logs são bem básicas e talvez não suficientes para fazer troubleshooting de OutOfMemoryError.

Podemos também exibir as informações de memória, CPU, system properties e locale usados pela JVM, o que é interessante para verificarmos se estamos definindo corretamente os parâmetros passados para aplicação. Por exemplo, para exibir as configurações de memória da VM basta executar:

java -XshowSettings:vm -version

E como resultado teremos (na minha máquina):

VM settings:
    Max. Heap Size (Estimated): 3.08G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.20.04)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.20.04, mixed mode)

Outras categorias podem ser informadas:

java -XshowSettings:vm -version         # VM settings:
java -XshowSettings:system -version     # Operating System Metrics
java -XshowSettings:properties -version # Property settings
java -XshowSettings:locale -version     # Locale settings
java -XshowSettings:all -version        # All settings

Referências

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment