jmap
vs. jmap -F
, bem como jstack
vs. jstack -F
usar mecanismos completamente diferentes para se comunicar com a JVM de destino.
jmap / jstack
Quando executado sem -F
essas ferramentas, use o mecanismo de conexão dinâmica . Isso funciona da seguinte maneira.
Antes de se conectar ao processo Java 1234, jmap
cria um arquivo .attach_pid1234
no diretório de trabalho do processo de destino ou em /tmp
.
Em seguida, jmap
envia SIGQUIT
para o processo de destino. Quando a JVM captura o sinal e encontra .attach_pid1234
, ela inicia o AttachListener
encadeamento.
AttachListener
thread cria soquete de domínio UNIX /tmp/.java_pid1234
para ouvir comandos de ferramentas externas.
Por razões de segurança, quando uma conexão (de jmap
) é aceita, a JVM verifica se as credenciais do par de soquete são iguais a euid
e egid
do processo JVM. É por isso jmap
que não funcionará se executado por um usuário diferente (mesmo por root).
jmap
conecta-se ao soquete e envia o dumpheap
comando.
Este comando é lido e executado por AttachListener
encadeamento da JVM. Todas as saídas são enviadas de volta ao soquete. Como o dump do heap é feito em processo diretamente pela JVM, a operação é muito rápida. No entanto, a JVM pode fazer isso apenas em pontos seguros . Se um ponto seguro não puder ser alcançado (por exemplo, o processo está travado, não está respondendo ou um longo GC está em andamento), jmap
o tempo limite será atingido e falhará.
Vamos resumir os benefícios e as desvantagens do Dynamic Attach.
Prós.
- O dump de heap e outras operações são executadas de forma colaborativa pela JVM na velocidade máxima.
- Você pode usar qualquer versão de
jmap
ou jstack
para se conectar a qualquer outra versão de JVM.
Cons.
- A ferramenta deve ser executada pelo mesmo usuário (
euid
/ egid
) da JVM de destino.
- Pode ser usado apenas em JVMs ativos e íntegros.
- Não funcionará se o JVM de destino for iniciado com
-XX:+DisableAttachMechanism
.
jmap -F / jstack -F
Quando executado com -F
as ferramentas, alterne para o modo especial que apresenta Agente de manutenção do HotSpot . Neste modo, o processo de destino é congelado; as ferramentas lêem sua memória por meio de recursos de depuração do SO, ou seja, ptrace
no Linux.
jmap -F
invoca PTRACE_ATTACH
na JVM de destino. O processo de destino é suspenso incondicionalmente em resposta ao SIGSTOP
sinal.
A ferramenta lê a memória JVM usando PTRACE_PEEKDATA
. ptrace
pode ler apenas uma palavra por vez, portanto, muitas chamadas são necessárias para ler o grande heap do processo de destino. Isso é muito lento.
A ferramenta reconstrói estruturas internas da JVM com base no conhecimento da versão específica da JVM. Como diferentes versões de JVM têm diferentes layouts de memória, o -F
modo funciona apenas se jmap
vier do mesmo JDK que o processo Java de destino.
A ferramenta cria o próprio dump de heap e, em seguida, retoma o processo de destino.
Prós.
- Nenhuma cooperação da JVM de destino é necessária. Pode ser usado mesmo em um processo suspenso.
ptrace
funciona sempre que os privilégios de nível do sistema operacional são suficientes. Por exemplo, root
pode despejar processos de todos os outros usuários.
Cons.
- Muito lento para pilhas grandes.
- A ferramenta e o processo de destino devem ser da mesma versão do JDK.
- O ponto seguro não é garantido quando a ferramenta é conectada em modo forçado. Embora
jmap
tente lidar com todos os casos especiais, às vezes pode acontecer que a JVM de destino não esteja em um estado consistente.
Nota
Há uma maneira mais rápida de fazer despejos de heap no modo forçado. Primeiro, crie um coredump com e gcore
, em seguida, execute jmap
o arquivo principal gerado. Veja a questão relacionada .
Assim como ben_wing disse, você pode executar com:
(no meu caso o usuário é
jboss-as
, mas o seu poderia serjboss
ou outro.)Mas não foi o suficiente, porque me pediu uma senha (
[sudo] password for ec2-user:
), embora eu pudesse executarsudo
sem solicitar uma senha com outros comandos.Encontrei a solução aqui e só precisava adicionar outra
sudo
primeiro:Funciona com outros comandos como
jcmd
ejinfo
também.fonte
sudo
salva meu dia![root@v5 ~]# sudo sudo -u es jmap -dump:file=tmp.bin 26283
vira errosudo: jmap: command not found
. Já configurei o caminho java em .bash_profile, o que devo fazer.es
usuário, o.bash_profile
não está sendo aplicado (porque o perfil do bash está relacionado ao seu usuário, eu presumo). Eu aconselho para incluir o caminho java de uma forma mais global, ou talvez especificar o caminho java no comando, comosudo sudo -u es PATH="$PATH:/java/path" jmap -dump:file=tmp.bin 26283
(onde/java/path
é o caminho java, e certifique-se que temjmap
nele ).sudo sudo -u es /usr/java/jdk1.8.0_181-cloudera/bin/jmap -dump:file=tmp.bin 26283
funciona. Muito obrigado.Se seu aplicativo estiver sendo executado como um serviço systemd, você deve abrir o arquivo de serviço com o
/usr/lib/systemd/system/
nome de seu serviço e nomeado por ele. Em seguida, verifique se privateTmp atributo é verdadeiro.Se for verdadeiro, você deve alterá-lo para falso e, em seguida, atualizar o serviço pelo comando da seguinte maneira:
systemctl daemon-reload systemctl restart [servicename]
Se quiser executar jmap / jcmd antes de reiniciar, você pode usar o script execStop no arquivo de serviço. Basta colocar o comando nele e executarsystemctl stop [service name]
fonte