¿Cómo activar JMX en mi JVM para acceder con jconsole?

223

¿Cómo activar JMX en una JVM para acceder con jconsole?

Mauli
fuente
32
está permitido, y en realidad es solo un recordatorio para mí, porque siempre olvido de dónde copiar los parámetros y ahora sé dónde lo encuentro: -)
Mauli
20
Stack Exchange siempre ha alentado explícitamente a los usuarios a responder sus propias preguntas, consulte aquí: stackoverflow.com/help/self-answer
Tim Büthe
11
Más de una vez busqué algo en SO y encontré una pregunta respondida ... por mí mismo. Y uno de esos fue preguntado por mí también. Es por eso que es bueno poner sus propias respuestas. Además, piense en todas las otras personas que pueden haber encontrado su problema, si responde su pregunta, también las ayudará.
Mike Miller el
2
El documento actualizado para Java 8 está aquí
Andrew Johnston
@Mauren: ¿Puedes proporcionar una referencia a tu pregunta cerrada que respondiste tú mismo? Podría valer la pena discutir sobre Meta.
kevinarpe

Respuestas:

290

La documentación relevante se puede encontrar aquí:

http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html

Inicie su programa con los siguientes parámetros:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.rmi.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

Por ejemplo así:

java -Dcom.sun.management.jmxremote \
  -Dcom.sun.management.jmxremote.port=9010 \
  -Dcom.sun.management.jmxremote.local.only=false \
  -Dcom.sun.management.jmxremote.authenticate=false \
  -Dcom.sun.management.jmxremote.ssl=false \
  -jar Notepad.jar

-Dcom.sun.management.jmxremote.local.only=falseno es necesariamente obligatorio pero sin él no funciona en Ubuntu. El error sería algo como esto:

01 Oct 2008 2:16:22 PM sun.rmi.transport. customer .TCPTransport$AcceptLoop executeAcceptLoop
WARNING: RMI TCP Accept-0: accept loop for ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=37278] throws
java.io.IOException: The server sockets created using the LocalRMIServerSocketFactory only accept connections from clients running on the host where the RMI remote objects have been exported.
    at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:89)
    at sun.rmi.transport. customer .TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:387)
    at sun.rmi.transport. customer .TCPTransport$AcceptLoop.run(TCPTransport.java:359)
    at java.lang.Thread.run(Thread.java:636)

ver http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6754672

También tenga cuidado con lo-Dcom.sun.management.jmxremote.authenticate=false que hace que el acceso esté disponible para cualquier persona, pero si solo lo usa para rastrear la JVM en su máquina local, no importa.

Actualización :

En algunos casos no pude llegar al servidor. Esto se solucionó si configuro este parámetro también:-Djava.rmi.server.hostname=127.0.0.1

Mauli
fuente
99
El -Dcom.sun.management.jmxremote.local.only = false también se necesita en Centos ahora
LenW
1
Nit pick: es extraño para mí que com.sun.management.jmxremotetenga el valor predeterminado como true. (¡Gracias Sun!) Para ser súper claro, especialmente para aquellos menos familiarizados con los nobs de JMX, uso: com.sun.management.jmxremote=trueRef: docs.oracle.com/javase/8/docs/technotes/guides/management/…
kevinarpe
1
¡"-Djava.rmi.server.hostname" funcionó de maravilla para mí!
Orhun D.
1
configurar el nombre de host en localhost es muy importante si está intentando conectar a un servidor remoto a través del túnel SSH, que es un caso muy común.
Nikhil Owalekar
1
Eso solo funciona si desactivo el firewall en el servidor. Abrí el puerto 9010 / tcp en este ejemplo, por supuesto, también intenté agregar Dcom.sun.management.jmxremote.rmi.port=9011y abrir en el firewall, aún no puedo conectarme con el firewall activo. ¿Alguna idea? ¿Me he perdido algo?
Carmageddon
70

Ejecutar en un contenedor Docker introdujo una gran cantidad de problemas adicionales para conectarse, por lo que espero que esto ayude a alguien. Terminé necesitando agregar las siguientes opciones que explicaré a continuación:

-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=${DOCKER_HOST_IP}
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.rmi.port=9998

DOCKER_HOST_IP

A diferencia de usar jconsole localmente, debe anunciar una IP diferente de la que probablemente verá desde el contenedor. Deberá reemplazarlo ${DOCKER_HOST_IP}con la IP (nombre DNS) que se puede resolver externamente de su host Docker.

Puertos remotos JMX y RMI

Parece que JMX también requiere acceso a una interfaz de administración remota ( jstat ) que usa un puerto diferente para transferir algunos datos al arbitrar la conexión. No vi ningún lugar inmediatamente obvio jconsolepara establecer este valor. En el artículo vinculado, el proceso fue:

  • Intenta conectarte jconsolecon el registro habilitado
  • Fallar
  • Averigua qué puerto jconsoleintentó usar
  • Utilice iptables/ firewallreglas según sea necesario para permitir que ese puerto se conecte

Si bien eso funciona, ciertamente no es una solución automatizable. Opté por una actualización de jconsole a VisualVM ya que le permite especificar explícitamente el puerto en el que se jstatdestá ejecutando. En VisualVM, agregue un nuevo host remoto y actualícelo con valores correlacionados con los especificados anteriormente:

Agregar host remoto

Luego haga clic con el botón derecho en la nueva Conexión de host remoto y Add JMX Connection...

Agregar conexión JMX

No olvide marcar la casilla de verificación para Do not require SSL connection. Con suerte, eso debería permitirle conectarse.

Joel B
fuente
-Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.rmi.port=[...]es también la clave en caso de tunelizar JMX / RMI a través de SSH. Sin ellos, se accede a los objetos remotos utilizando la IP pública / principal / ... del servidor utilizando algún puerto aleatorio, que no se puede reenviar fácilmente.
Thorsten Schöning
1
Puedo confirmar que realmente necesita usar la IP externa al contenedor. Por ejemplo, no funciona con-Djava.rmi.server.hostname=0.0.0.0
raisercostin
Yo no tenía necesidad de usar DOCKER_HOST_IPen cualquier lugar - que acabo de utilizar localhosty ha remitido los puertos cuando se ejecuta la imagen ventana acoplable: -p 9998:9998, -p 9999:9999etc
Barney
9

Tenga en cuenta que Java 6 en la última encarnación permite que jconsole se adjunte a un proceso en ejecución incluso después de que se haya iniciado sin encantamientos JMX.

Si eso está disponible para usted, considere también jvisualvm, ya que proporciona una gran cantidad de información sobre los procesos en ejecución, incluido un generador de perfiles.

Thorbjørn Ravn Andersen
fuente
3
Esto solo funciona si está ejecutando jconsole en el mismo host que la JVM que está tratando de monitorear.
Gray
1
@ Thorbjorn Si inicio mi programa java sin ningún parámetro e intento conectarme con jconsole, veo en mi programa en la lista, pero cuando intento conectarlo falla. Creo que es por falta de certificados SSL. Solo quería ver la demostración, por lo tanto, tuve que usar los parámetros especificados en la respuesta del usuario 3013578 y funcionó para mí (JDK 1.7, Windows 8.1, 64 bits).
Capitán Jack Sparrow
2
La API de conexión requiere que jconsole tenga la misma JVM de 32/64 bits que el programa lanzado en algunas plataformas.
Thorbjørn Ravn Andersen
1
¿Es posible deshabilitar este comportamiento?
kevinarpe
7

Estoy usando WAS ND 7.0

Mi JVM necesita todos los siguientes argumentos para ser monitoreados en JConsole

    -Djavax.management.builder.initial= 
    -Dcom.sun.management.jmxremote 
    -Dcom.sun.management.jmxremote.port=8855 
    -Dcom.sun.management.jmxremote.authenticate=false 
    -Dcom.sun.management.jmxremote.ssl=false
usuario3013578
fuente
Sí, su respuesta funcionó para mí (JDK 1.7, Windows 8.1 64 bit)
Capitán Jack Sparrow
6

En Linux, utilicé los siguientes parámetros:

-Djavax.management.builder.initial= 
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9010 
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false

y también edité /etc/hostspara que el nombre de host se resuelva en la dirección de host (192.168.0.x) en lugar de la dirección de bucle invertido (127.0.0.1)

alex.pulver
fuente
2

Ejecute su aplicación Java con los siguientes parámetros de línea de comandos:

-Dcom.sun.management.jmxremote.port=8855
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

Es importante utilizar el parámetro -Dcom.sun.management.jmxremote.ssl = false si no desea configurar certificados digitales en el host jmx.

Si inició su aplicación en una máquina con la dirección IP 192.168.0.1 , abra jconsole , coloque 192.168.0.1:8855 en el campo Proceso remoto y haga clic en Conectar .

Wasif
fuente
¿Cuál es el comportamiento esperado si lo olvida -Dcom.sun.management.jmxremote.ssl=false? ¿Debería jconsolemostrar un error, o simplemente no se conectaría en silencio?
amacleod el
2

junto con los siguientes parámetros de línea de comando,

-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

A veces, en los servidores de Linux, la conexión imx no se realiza correctamente. Esto se debe a que, en el host Linux de la nube, en / etc / hosts para que el nombre del host se resuelva en la dirección del host.

la mejor manera de solucionarlo es hacer ping al servidor Linux en particular desde otra máquina en la red y usar esa dirección IP de host en el

-Djava.rmi.server.hostname=IP address that obtained when you ping that linux server.

Pero nunca confíe en la ipaddress que obtiene del servidor linux usando ifconfig.me. la ip que obtienes allí está enmascarada y está presente en el archivo host.

Phani Kumar
fuente
1

Primero debe verificar si su proceso de Java ya se está ejecutando con parámetros JMX. Hacer esto:

ps -ef | grep java

Verifique el proceso de Java que necesita monitorear. Si puede ver el parámetro jmx rmi Djmx.rmi.registry.port = xxxx , use el puerto mencionado aquí en su visualvm de java para conectarlo de forma remota con una conexión jmx.

Si no se ejecuta a través del puerto jmx rmi, entonces debe ejecutar su proceso java con los parámetros mencionados a continuación:

-Djmx.rmi.registry.port=1234 -Djmx.rmi.port=1235 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

Nota: los números de puerto se basan en su elección.

Ahora puede usar este puerto para la conexión jmx. Aquí está el puerto 1234.

Abhay S
fuente
¿Debería poder ver el puerto 1234 en uso por jmx una vez que ejecute esto? sudo lsof -i:1234no muestra nada para mí
Gorgon_Union
1

Paso 1: Ejecute la aplicación usando los siguientes parámetros.

-Dcom.sun.management.jmxremote.port=9999 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false

Los argumentos anteriores vinculan la aplicación al puerto 9999.

Paso 2: Inicie jconsole ejecutando el comando jconsole en el símbolo del sistema o terminal.

Seleccione 'Proceso remoto:' e ingrese la url como {IP_Address}: 9999 y haga clic en el botón Conectar para conectarse a la aplicación remota.

Puede consultar este enlace para completar la solicitud.

Hari Krishna
fuente