jmap
vs. jmap -F
, así como jstack
vs. jstack -F
utilizar mecanismos completamente diferentes para comunicarse con la JVM de destino.
jmap / jstack
Cuando se ejecuta sin -F
estas herramientas, utilice Dynamic Attach Mechanism . Esto funciona de la siguiente manera.
Antes de conectarse al proceso 1234 de Java, jmap
crea un archivo .attach_pid1234
en el directorio de trabajo del proceso de destino o en /tmp
.
Luego jmap
envía SIGQUIT
al proceso de destino. Cuando JVM detecta la señal y la encuentra .attach_pid1234
, inicia el AttachListener
hilo.
AttachListener
thread crea un socket de dominio UNIX /tmp/.java_pid1234
para escuchar comandos de herramientas externas.
Por razones de seguridad cuando una conexión (de jmap
se acepta), verifica JVM que las credenciales de los pares socket son iguales a euid
y egid
de proceso JVM. Es por eso jmap
que no funcionará si lo ejecuta un usuario diferente (incluso por root).
jmap
se conecta al enchufe y envía el dumpheap
comando.
Este comando es leído y ejecutado por el AttachListener
hilo de la JVM. Toda la salida se envía de vuelta al enchufe. Dado que el volcado de pila se realiza en proceso directamente por JVM, la operación es realmente rápida. Sin embargo, JVM solo puede hacer esto en puntos seguros . Si no se puede alcanzar un punto seguro (por ejemplo, el proceso se bloquea, no responde o hay un GC largo en curso), jmap
se agotará el tiempo de espera y fallará.
Resumamos los beneficios y los inconvenientes de Dynamic Attach.
Pros.
- El volcado de pila y otras operaciones se ejecutan en colaboración con JVM a la máxima velocidad.
- Puede utilizar cualquier versión de
jmap
o jstack
para conectarse a cualquier otra versión de JVM.
Contras.
- La herramienta debe ejecutarla el mismo usuario (
euid
/ egid
) que la JVM de destino.
- Solo se puede usar en JVM en vivo y en buen estado.
- No funcionará si se inicia la JVM de destino
-XX:+DisableAttachMechanism
.
jmap -F / jstack -F
Cuando se ejecuta con -F
las herramientas, cambie al modo especial que cuenta con HotSpot Serviceability Agent . En este modo, el proceso de destino se congela; las herramientas leen su memoria a través de las instalaciones de depuración del sistema operativo, es decir, ptrace
en Linux.
jmap -F
invoca PTRACE_ATTACH
en la JVM de destino. El proceso objetivo se suspende incondicionalmente en respuesta a la SIGSTOP
señal.
La herramienta lee la memoria JVM usando PTRACE_PEEKDATA
. ptrace
puede leer solo una palabra a la vez, por lo que se requieren demasiadas llamadas para leer el gran montón del proceso de destino. Esto es muy y muy lento.
La herramienta reconstruye las estructuras internas de la JVM basándose en el conocimiento de la versión particular de la JVM. Dado que las diferentes versiones de JVM tienen un diseño de memoria diferente, el -F
modo solo funciona si jmap
proviene del mismo JDK que el proceso Java de destino.
La herramienta crea un volcado de montón y luego reanuda el proceso de destino.
Pros.
- No se requiere cooperación de la JVM de destino. Puede usarse incluso en un proceso colgado.
ptrace
funciona siempre que los privilegios de nivel de sistema operativo son suficientes. Por ejemplo, root
puede volcar procesos de todos los demás usuarios.
Contras.
- Muy lento para grandes montones.
- La herramienta y el proceso de destino deben ser de la misma versión de JDK.
- El punto seguro no está garantizado cuando la herramienta se conecta en modo forzado. Aunque
jmap
intenta manejar todos los casos especiales, a veces puede suceder que la JVM de destino no esté en un estado consistente.
Nota
Existe una forma más rápida de realizar volcados de pila en modo forzado. Primero, cree un volcado de memoria con gcore
y luego ejecute jmap
el archivo central generado. Vea la pregunta relacionada .
Al igual que ben_wing dicho, puede ejecutar con:
(en mi caso el usuario es
jboss-as
, pero el tuyo podría serlojboss
o algún otro).Pero no fue suficiente, porque me pidió una contraseña (
[sudo] password for ec2-user:
), aunque pude ejecutarsudo
sin pedirme una contraseña con otros comandos.Encontré la solución aquí , y solo necesitaba agregar otra
sudo
primero:Funciona con otros comandos como
jcmd
yjinfo
también.fuente
sudo
me salva el día![root@v5 ~]# sudo sudo -u es jmap -dump:file=tmp.bin 26283
se convierte en errorsudo: jmap: command not found
. Ya configuré la ruta de Java en .bash_profile, ¿qué debo hacer?es
usuario,.bash_profile
no se está aplicando (porque el perfil de bash está relacionado con su usuario, supongo). Aconsejo a incluir la ruta de Java de una manera más global, o tal vez especificar la ruta de Java en el comando, comosudo sudo -u es PATH="$PATH:/java/path" jmap -dump:file=tmp.bin 26283
(donde/java/path
es la ruta de Java, y asegurarse de que se disponejmap
en ella ).sudo sudo -u es /usr/java/jdk1.8.0_181-cloudera/bin/jmap -dump:file=tmp.bin 26283
funciona. Muchas gracias.Si su aplicación se ejecuta como un servicio systemd, debe abrir el archivo de servicio que se encuentra debajo
/usr/lib/systemd/system/
y con el nombre de su servicio. Luego, verifique si el atributo privateTmp es verdadero.Si es verdadero, debe cambiarlo a falso, luego actualice el servicio con el comando de la siguiente manera:
systemctl daemon-reload systemctl restart [servicename]
Si desea ejecutar jmap / jcmd antes de reiniciar, puede usar el script execStop en el archivo de servicio. Solo ingrese el comando y ejecutesystemctl stop [service name]
fuente