Comment activer JMX sur ma JVM pour accéder à jconsole?

223

Comment activer JMX sur une JVM pour un accès avec jconsole?

Mauli
la source
32
c'est autorisé, et en fait ce n'est qu'un rappel pour moi, car j'oublie toujours d'où copier les paramètres et maintenant je sais où je le trouve :-)
Mauli
20
Stack Exchange a toujours explicitement encouragé les utilisateurs à répondre à leurs propres questions, voir ici: stackoverflow.com/help/self-answer
Tim Büthe
11
Plus d'une fois, j'ai cherché SO quelque chose et trouvé une question répondue ... par moi-même. Et l'un d'eux a également été demandé par moi. C'est pourquoi il est bon de mettre vos propres réponses. Pensez également à toutes les autres personnes qui ont pu rencontrer votre problème, si vous répondez à votre question, vous les aiderez aussi.
Mike Miller,
2
Le document mis à jour pour Java 8 est ici
Andrew Johnston
@Mauren: Pouvez-vous fournir une référence à votre question fermée à laquelle vous avez répondu vous-même? Il pourrait être utile de discuter de Meta.
kevinarpe

Réponses:

290

La documentation pertinente peut être trouvée ici:

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

Démarrez votre programme avec les paramètres suivants:

-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

Par exemple, comme ceci:

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=falsen'est pas nécessairement requis mais sans lui, il ne fonctionne pas sur Ubuntu. L'erreur serait quelque chose comme ceci:

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)

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

-Dcom.sun.management.jmxremote.authenticate=falseFaites également attention à ce qui rend l'accès accessible à tous, mais si vous ne l'utilisez que pour suivre la JVM sur votre machine locale, cela n'a pas d'importance.

Mise à jour :

Dans certains cas, je n'ai pas pu atteindre le serveur. Cela a ensuite été corrigé si je définissais également ce paramètre:-Djava.rmi.server.hostname=127.0.0.1

Mauli
la source
9
Le -Dcom.sun.management.jmxremote.local.only = false est également nécessaire sur Centos maintenant
LenW
1
Nit pick: C'est bizarre pour moi qui com.sun.management.jmxremotea la valeur par défaut true. (Merci Sun!) Pour être très clair, en particulier pour ceux qui connaissent moins les JMX, j'utilise: com.sun.management.jmxremote=trueRéf: docs.oracle.com/javase/8/docs/technotes/guides/management/…
kevinarpe
1
"-Djava.rmi.server.hostname" a fonctionné comme un charme pour moi!
Orhun D.
1
définir le nom d'hôte sur localhost est très important si vous essayez de connecter un à un serveur distant via le tunnel SSH, ce qui est un cas très courant.
Nikhil Owalekar
1
Cela ne fonctionne que si je désactive le pare-feu sur le serveur. J'ai ouvert le port 9010 / tcp dans cet exemple bien sûr, j'ai également essayé d'ajouter Dcom.sun.management.jmxremote.rmi.port=9011et d'ouvrir dans le pare-feu - je ne peux toujours pas me connecter avec le pare-feu en marche. Des pensées? Ai-je raté quelque chose?
Carmageddon
70

L'exécution dans un conteneur Docker a introduit toute une série de problèmes supplémentaires pour la connexion, donc j'espère que cela aide quelqu'un. J'ai fini par avoir besoin d'ajouter les options suivantes que j'expliquerai ci-dessous:

-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

Contrairement à l'utilisation de jconsole localement, vous devez publier une IP différente de celle que vous verrez probablement dans le conteneur. Vous devrez le remplacer ${DOCKER_HOST_IP}par l'IP (nom DNS) résolvable en externe de votre hôte Docker.

Ports JMX à distance et RMI

Il semble que JMX nécessite également l'accès à une interface de gestion à distance ( jstat ) qui utilise un port différent pour transférer certaines données lors de l'arbitrage de la connexion. Je n'ai vu aucun endroit immédiatement évident jconsolepour définir cette valeur. Dans l'article lié, le processus était le suivant:

  • Essayez de vous connecter jconsoleavec la journalisation activée
  • Échouer
  • Découvrez quel port a jconsoletenté d'utiliser
  • Utilisez iptables/ firewallrules si nécessaire pour permettre à ce port de se connecter

Bien que cela fonctionne, ce n'est certainement pas une solution automatisable. J'ai opté pour une mise à niveau de jconsole vers VisualVM car cela vous permet de spécifier explicitement le port sur lequel jstatds'exécute. Dans VisualVM, ajoutez un nouvel hôte distant et mettez-le à jour avec des valeurs qui correspondent à celles spécifiées ci-dessus:

Ajouter un hôte distant

Cliquez ensuite avec le bouton droit sur la nouvelle connexion de l'hôte distant et Add JMX Connection...

Ajouter une connexion JMX

N'oubliez pas de cocher la case Do not require SSL connection. J'espère que cela devrait vous permettre de vous connecter.

Joel B
la source
-Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.rmi.port=[...]est également la clé en cas de tunneling JMX / RMI via SSH. Sans cela, les objets distants sont accessibles en utilisant l'IP publique / principale / ... du serveur en utilisant un port aléatoire, qui ne peut pas être transféré facilement.
Thorsten Schöning
1
Je peux confirmer que vous avez vraiment besoin d'utiliser l'IP externe au conteneur. Par exemple, cela ne fonctionne pas avec-Djava.rmi.server.hostname=0.0.0.0
raisercostin
Je n'avais pas besoin d'utiliser DOCKER_HOST_IPn'importe où - j'ai juste utilisé localhostet transféré les ports lors de l'exécution de l'image docker: -p 9998:9998, -p 9999:9999etc.
Barney
9

Notez que Java 6 dans la dernière incarnation permet à jconsole de s'attacher à un processus en cours même après son démarrage sans incantations JMX.

Si cela vous est disponible, pensez également à jvisualvm car il fournit une mine d'informations sur les processus en cours d'exécution, y compris un profileur.

Thorbjørn Ravn Andersen
la source
3
Cela ne fonctionne que si vous exécutez jconsole sur le même hôte que la machine virtuelle Java que vous essayez de surveiller.
Gray
1
@ Thorbjorn Si je démarre mon programme java sans aucun paramètre et essaie de me connecter avec jconsole, je vois dans mon programme dans la liste mais quand j'essaye de me connecter il échoue. Je pense que c'est à cause du manque de certificats SSL. Je voulais juste voir la démo, j'ai donc dû utiliser les paramètres spécifiés dans la réponse de user3013578 et cela a fonctionné pour moi (JDK 1.7, Windows 8.1, 64 bits).
Captain Jack Sparrow
2
L'API attach nécessite que jconsole ait la même JVM 32/64 bits que le programme lancé sur certaines plates-formes.
Thorbjørn Ravn Andersen
1
Est-il possible de désactiver ce comportement?
kevinarpe
7

J'utilise WAS ND 7.0

Ma machine virtuelle Java a besoin de tous les arguments suivants pour être surveillés dans 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
user3013578
la source
Oui, votre réponse a fonctionné pour moi (JDK 1.7, Windows 8.1 64 bits)
Captain Jack Sparrow
6

Sous Linux, j'ai utilisé les paramètres suivants:

-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

et aussi j'ai édité de /etc/hostssorte que le nom d'hôte se résout à l'adresse d'hôte (192.168.0.x) plutôt qu'à l'adresse de bouclage (127.0.0.1)

alex.pulver
la source
2

Exécutez votre application java avec les paramètres de ligne de commande suivants:

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

Il est important d'utiliser le -Dcom.sun.management.jmxremote.ssl = false paramètre si vous ne souhaitez pas configurer de certificats numériques sur l'hôte jmx.

Si vous avez démarré votre application sur une machine ayant l'adresse IP 192.168.0.1 , ouvrez jconsole , mettez 192.168.0.1:8855 dans le champ Processus distant et cliquez sur Connecter .

Wasif
la source
Quel est le comportement attendu si vous oubliez -Dcom.sun.management.jmxremote.ssl=false? Devrait jconsoleafficher une erreur, ou échouerait-il simplement à se connecter?
amacleod
2

ainsi que les paramètres de ligne de commande ci-dessous,

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

Parfois, dans les serveurs Linux, la connexion imx ne réussit pas. c'est parce que, dans l'hôte cloud linux, dans / etc / hosts de sorte que le nom d'hôte se résout en adresse d'hôte.

la meilleure façon de le résoudre est d'envoyer une requête ping au serveur linux particulier à partir d'une autre machine du réseau et d'utiliser cette adresse IP hôte dans le

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

Mais ne vous fiez jamais à l'adresse IP que vous obtenez du serveur Linux en utilisant ifconfig.me. l'IP que vous obtenez est masquée et présente dans le fichier hôte.

Phani Kumar
la source
1

Vous devez d'abord vérifier si votre processus java est déjà en cours d'exécution avec les paramètres JMX. Faites ceci:

ps -ef | grep java

Vérifiez votre processus java que vous devez surveiller. Si vous pouvez voir le paramètre jmx rmi Djmx.rmi.registry.port = xxxx, utilisez le port mentionné ici dans votre visualvm java pour le connecter à distance sous connexion jmx.

S'il ne fonctionne pas via le port jmx rmi, vous devez exécuter votre processus java avec les paramètres mentionnés ci-dessous:

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

Remarque: les numéros de port sont basés sur votre choix.

Vous pouvez maintenant utiliser ce port pour la coneection jmx. Ici, c'est le port 1234.

Abhay S
la source
Devriez-vous être en mesure de voir le port 1234 utilisé par jmx une fois que vous l'exécutez? sudo lsof -i:1234ne montre rien pour moi
Gorgon_Union
1

Étape 1: exécutez l'application à l'aide des paramètres suivants.

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

Les arguments ci-dessus lient l'application au port 9999.

Étape 2: Lancez jconsole en exécutant la commande jconsole dans l'invite de commande ou le terminal.

Sélectionnez 'Processus distant:' et entrez l'URL comme {IP_Address}: 9999 et cliquez sur le bouton Connecter pour vous connecter à l'application distante.

Vous pouvez renvoyer ce lien pour une demande complète.

Hari Krishna
la source