2015-02-26 2 views
3

J'utilise les paramètres JVM suivants pour démarrer une machine virtuelle Java avec le débogueur hostpot.Identifier Java jdwp Port affecté au débogueur (Ephemeral)

-Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=0 

Notez que je suis le port zéro assigne, de sorte que la machine virtuelle Java demande au système d'exploitation pour un port éphémère. Ceci est critique pour mon cas d'utilisation, pour m'assurer que la JVM ne manquera pas de démarrer en raison de la contention d'un port prédéfini.

En conséquence ma machine virtuelle démarre en place, et l'entrée du journal suivant est émis à stdout:

Listening for transport dt_socket at address: XXXX 

Je voudrais trouver un moyen d'identifier le port de débogage à l'intérieur ou à l'extérieur de la machine virtuelle Java, il serait donc possible pour moi de l'enregistrer dans un serveur de gestion d'état.

Quelles options sont disponibles pour ce cas d'utilisation? Je l'ai considéré ce qui suit, avec peu de joie:

  • JMX Connecteur - Se connecter en utilisant JConsole au processus, trouver des détails qui MBean quel port est utilisé. Cependant, je ne peux pas trouver un tel MBean
  • Registre RMI - Est-il possible que l'agent de débogage s'enregistre lui-même dans un registre RMI? Je n'ai trouvé aucune preuve que cela pourrait fonctionner.
  • Agent Java - Spécifie un agent JVM qui pourrait intercepter certains aspects du débogueur et obtenir les détails du port, encore une fois aucune preuve pour soutenir la faisabilité de cette idée.
+0

Exécutez un programme pour affecter le port et relâchez-le au lieu de passer 0 ici. C'est ainsi que fonctionne le plugin build-helper-maven-plugin. – bmargulies

+0

@bmargulies - Cela suppose qu'aucun autre processus n'ouvre le même numéro de port entre le wrapper qui le ferme et l'application qui l'ouvre.Cela me fait me sentir un peu mal à l'aise dans une application de production. – jwa

Répondre

8

A partir de l'intérieur VM:

Properties props = sun.misc.VMSupport.getAgentProperties(); 
    System.out.println(props.getProperty("sun.jdwp.listenerAddress")); 

De l'application extérieure:

VirtualMachine vm = com.sun.tools.attach.VirtualMachine.attach(PID); 
    try { 
     Properties props = vm.getAgentProperties(); 
     System.out.println(props.getProperty("sun.jdwp.listenerAddress")); 
    } finally { 
     vm.detach(); 
    } 

Les deux ne font pas partie d'une norme. Applicable uniquement à OpenJDK/Oracle JDK.

+0

Ceci est réussi. Notez que cette option n'est exportée que si l'argument 'server = y' est spécifié dans le cadre de' -Xrunjdwp: server = y, transport = dt_socket, adresse = 1234, suspend = n' – jwa

0

Peut-être que vous pourriez commencer avec.

netstat -tlnp 

Ceci vous donne une liste de tous les processus écoutant sur un port TCP local. Par exemple:

tcp 0 0 0.0.0.0:35688  0.0.0.0:*  LISTEN 26733/java 
 
35688 - the ephemeral port 
java - the program name which is listening 
26733 - the PID of the process 

Si vous avez besoin d'une granularité plus fine des processus java, vous pouvez utiliser ps pour recueillir des informations sur le processus.

ps x -p 26733

pourrait retourner quelque chose comme

26733 pts/1 0:00 java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=0 Scratch

+0

Le problème que je prévois ici est que l'application ouvre plus d'un port éphémère, car il a d'autres cas d'utilisation de réseau général. Par conséquent, il serait difficile de faire la distinction entre le port jdwp et les autres. – jwa

+0

Vous voulez dire que vous démarrez plusieurs processus qui auraient la ligne de commande? – SubOptimal

+0

Non, pour clarifier. Si l'application ouvre plus d'un port, netstat listera tous les ports qui appartiennent au processus. Par conséquent, il ne serait pas possible d'identifier les ports sur lesquels le débogueur écoute. – jwa