Neste post será apresentado como investigar o problema de ‘ Out of memory : unable to create new native thread’ do lado do sistema operacional .
1) Causa :
Por algum motivo a aplicação para e é apresentado o erro abaixo :
Caused by: java.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:714) at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:949) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1371)
Às vezes por causa do limite imposto no sistema operacional Linux / Unix a aplicação não consegue abrir mais processos e com isso tomamos este erro, sendo assim parando a aplicação e reiniciar a JVM não seria uma melhor solução , pois devido a limitação no SO o problema ocorrerá novamente.
2) Análise no Sistema Operacional :
Por padrão cada usuário no SO já com o Max Files limitado para 1024 threads.
Quando é apresentado em específico entramos no usuário da aplicação e rodamos o comando para ver o número de threads :
su - appuser ulimit -a
Segue um exemplo de um log de Jboss quando é apresentado o problema :
Para definirmos o valor ideal para que o usuário da aplicação tenha o valor o ideal para rodar sem problemas :
* Verificamos o valor total que o sistema operacional suporta /proc/sys/fs/file-max :
* Após chegar ao valor obtido incluímos os valores abaixo no arquivo /etc/security/limits.conf :
appuser soft nofile 30000 appuser hard nofile 30000 appuser soft nproc 30000 appuser hard nproc 30000
* Monitoramos a solução com o script no link :
No exemplo abaixo altere o APPUSER nas variáveis pelo usuário que o appserver usa :
#!/bin/bash threads=" `ps h -Led -o user | sort | uniq -c | sort -n | grep APPUSER | awk '{print $1}'`" processo="`pgrep -fl APPUSER | head -n1 | awk '{print $1}'`" echo $"Numeros de threads criadas pelo usuario APPUSER --> `echo $threads`" echo "" echo "" echo $"Processo que o APPUSER esta usando --> `echo $processo`" echo "" echo "" echo "Valor do usuario do APPUSER em /etc/security/limits.conf" runuser -l appuser -c 'ulimit -a | grep "max user processes"'
Com esta análise já podemos acompanhar a aplicação no lado do Sistema Operacional.
* Aumentando o valor total de threads de SO :
Não é recomendado que seja configurado diretamente o no Kernel este o valor total em um servidor em produção , caso seja uma aplicação de alto desempenho , é sugerido que se faça diversos testes antes de ir para a produção sem haver mudanças bruscas.
Caso seja necessário alterar a nível total de SO , podemos aumentar seguindo os passos :
Inclua os valores no final do arquivo /etc/sysctl.conf :
# Controls the maximum number of threads kernel.threads-max = 200000
Para iniciar os valores rode o comando :
sysctl -p
Referências :