Executando jmap obtendo Incapaz de abrir o arquivo de socket

88

Tive de executar jmappara obter o despejo de pilha do meu processo. mas jvmretornou:

Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding

Então eu usei -F:

./jmap -F -dump:format=b,file=heap.bin 10330
Attaching to process ID 10331, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.51-b03
Dumping heap to heap.bin ...
  1. Usar -F está tudo bem para fazer despejo de heap?
  2. Estou esperando 20 minutos e ainda não terminei. Alguma ideia por quê?
Rayman
fonte

Respostas:

187

jmapvs. jmap -F, bem como jstackvs. jstack -Fusar mecanismos completamente diferentes para se comunicar com a JVM de destino.

jmap / jstack

Quando executado sem -Fessas ferramentas, use o mecanismo de conexão dinâmica . Isso funciona da seguinte maneira.

  1. Antes de se conectar ao processo Java 1234, jmapcria um arquivo .attach_pid1234no diretório de trabalho do processo de destino ou em /tmp.

  2. Em seguida, jmapenvia SIGQUITpara o processo de destino. Quando a JVM captura o sinal e encontra .attach_pid1234, ela inicia o AttachListenerencadeamento.

  3. AttachListenerthread cria soquete de domínio UNIX /tmp/.java_pid1234para ouvir comandos de ferramentas externas.

  4. 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 euide egiddo processo JVM. É por isso jmapque não funcionará se executado por um usuário diferente (mesmo por root).

  5. jmapconecta-se ao soquete e envia o dumpheapcomando.

  6. Este comando é lido e executado por AttachListenerencadeamento 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), jmapo 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 jmapou jstackpara 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 -Fas 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, ptraceno Linux.

  1. jmap -Finvoca PTRACE_ATTACHna JVM de destino. O processo de destino é suspenso incondicionalmente em resposta ao SIGSTOPsinal.

  2. A ferramenta lê a memória JVM usando PTRACE_PEEKDATA. ptracepode 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.

  3. 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 -Fmodo funciona apenas se jmapvier do mesmo JDK que o processo Java de destino.

  4. 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.
  • ptracefunciona sempre que os privilégios de nível do sistema operacional são suficientes. Por exemplo, rootpode 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 jmaptente 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 jmapo arquivo principal gerado. Veja a questão relacionada .

apangina
fonte
85

Acabei de descobrir que jmap (e presumivelmente jvisualvm ao usá-lo para gerar um despejo de heap) impõe que o usuário executando o jmap deve ser o mesmo usuário executando o processo que tenta ser despejado.

no meu caso, o jvm para o qual eu quero um despejo de heap está sendo executado pelo usuário linux "jboss". então, onde sudo jmap -dump:file.bin <pid>estava relatando "Não foi possível abrir o soquete:", consegui pegar meu despejo de heap usando:

sudo -u jboss jmap -dump:file.bin <pid>
ben_wing
fonte
Acho que deve ser \ -dump: file.bin <pid>, pois você precisa escapar do - ao passar o parâmetro do sudo para o jmap.
adam
É isso! Você precisa sudo para jmap e jcmd também.
xtian
uau .. Isso realmente funcionou. Esta deve ser a resposta aceita
Lalit Rao
3

Assim como ben_wing disse, você pode executar com:

sudo -u jboss-as jmap -dump:file.bin <pid>

(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 sudoprimeiro:

sudo sudo -u jboss-as jmap -dump:file.bin <pid>

Funciona com outros comandos como jcmde jinfotambém.

Lucas basquerotto
fonte
O dobro sudosalva meu dia!
Sher10ck
[root@v5 ~]# sudo sudo -u es jmap -dump:file=tmp.bin 26283 vira erro sudo: jmap: command not found. Já configurei o caminho java em .bash_profile, o que devo fazer.
roamer
@roamer Talvez seja porque quando você executa como o esusuário, o .bash_profilenã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, como sudo sudo -u es PATH="$PATH:/java/path" jmap -dump:file=tmp.bin 26283(onde /java/pathé o caminho java, e certifique-se que tem jmapnele ).
Lucas Basquerotto
Eu configuro o caminho do java em /home/es/.bash_profile e posso usar o jmap ao fazer login com o usuário es. Este cmd sudo sudo -u es /usr/java/jdk1.8.0_181-cloudera/bin/jmap -dump:file=tmp.bin 26283funciona. Muito obrigado.
roamer
2

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]

Simples
fonte
Antes de atualizar o /usr/lib/systemd/system/elasticsearch.service, definindo privateTmp como false, recebi este erro: Não é possível abrir o arquivo de soquete: o processo de destino não está respondendo ou o HotSpot VM não está carregado - embora eu estivesse executando o jmap como o usuário
elasticsearch