2010-12-30 6 views
3

Wenn Sie beim Starten einer JVM die Systemeigenschaft "com.sun.management.jmxremote" festlegen, können Sie jconsole oder visualvm ausführen und eine Verbindung mit diesem lokalen mBeanServer herstellen. Ich möchte dasselbe tun, was sie tun, aber ich kann nicht herausfinden, wie.Wie verbinde ich mich mit einem mBeanServer in einem anderen lokalen Prozess?

Gibt es eine Service-URL, mit der Sie eine lokal laufende JVM identifizieren können?

Ich weiß, dass ich dies tun konnte, indem ich einen jmxmp oder rmi Listener an einem bestimmten Port aufbaute und dann mit diesem Port verband, aber ich möchte das nicht tun, weil ich die Ports verwalten muss und weiß was Port geht zu dem jvm (wir laufen mehrere jvms auf dem gleichen Server).

Antwort

1

Sie benötigen die Attach API. Er sucht nach laufenden [JVM-fähigen] API-fähigen JVMs auf demselben Host und gibt sowohl Metadaten zurück, als auch einen JMXConnector. Es ist im Grunde das, was Sie sehen, wenn Sie JConsole starten, und das Verbindungsmenü zeigt laufende JVMs an, einschließlich Java 1.6+ -Instanzen, die nicht mit speziellen JMX-Befehlszeilenanweisungen gestartet wurden.

// Nicholas

+0

befestigen API wird mir ein Handle für die JVM, aber nicht auf die MBeanServer in dieser JVM. Das Javadoc für die Attach-API zeigt ein Beispiel, wie ein Agent mit diesem Aufruf remote geladen wird: –

+0

Richtig. Wenn Sie den eingebauten JRE-Verwaltungsagenten (/jre/lib/management-agent.jar) laden und den Listening-Port angeben (z. B. vm.loadAgent (Agent, "com.sun.management.jmxremote.port = 5000");), dann können Sie die JMX Remoting API verwenden, um sich mit dem MBeanServer auf Port 5000 zu verbinden. Wenn Sie nach einer Möglichkeit suchten, auf den MBeanServer in einer JVM ohne Portzugriff zuzugreifen ... bin ich mir nicht sicher .... Sie könnten in der Lage sein, ein FIFO-basiertes Protokoll oder etwas zu entwickeln. – Nicholas

+0

Ich wollte keine Verbindung ohne Port-Zugriff herstellen ... Ich wollte einfach nicht angeben müssen, welcher Port verwendet werden soll. Stellt sich heraus, wenn Sie keinen Port angeben (d. H. Aufruf von vm.loadAgent (Agent, "com.sun.management.jmxremote")), dann wählt der jvm einen zufälligen hohen Port aus. Ich kann dann vm.getAgentProperties(). Get ("com.sun.management.jmxremote.localConnectorAddress") aufrufen, um eine URL zur Verbindung mit dem mBeanServer zu erhalten. Danke Nicholas für Ihre Hilfe! http://blog.fastconnect.fr/?p=385 –

7

Dank Nicholas und Scott für die Post und Diskussion. Ich konnte das anhand dieser Informationen und einiger Versuche zusammenstellen.

Teilen, damit andere nicht die gleiche Beinarbeit machen müssen. Dies wird an eine JVM angehängt und die Speicherbelegung abgerufen. Die

import com.sun.tools.attach.VirtualMachine; 
import com.sun.tools.attach.VirtualMachineDescriptor; 
import com.sun.tools.attach.spi.AttachProvider; 

import javax.management.MBeanServerConnection; 
import javax.management.ObjectName; 
import javax.management.openmbean.CompositeData; 
import javax.management.remote.JMXConnector; 
import javax.management.remote.JMXConnectorFactory; 
import javax.management.remote.JMXServiceURL; 

public class AttachFun { 

    public static void main(String[] args) throws Exception { 
     final AttachProvider attachProvider = AttachProvider.providers().get(0); 

     VirtualMachineDescriptor descriptor = null; 
     for (VirtualMachineDescriptor virtualMachineDescriptor : attachProvider.listVirtualMachines()) { 
      if (pickThisOne(virtualMachineDescriptor)) { 
       descriptor = virtualMachineDescriptor; 
       break; 
      } 
     } 

     if (descriptor == null) throw new RuntimeException("You didn't pick one"); 

     final VirtualMachine virtualMachine = attachProvider.attachVirtualMachine(descriptor); 
     virtualMachine.loadAgent("/System/Library/Frameworks/JavaVM.framework/Home/lib/management-agent.jar", "com.sun.management.jmxremote"); 
     final Object portObject = virtualMachine.getAgentProperties().get("com.sun.management.jmxremote.localConnectorAddress"); 

     final JMXServiceURL target = new JMXServiceURL(portObject + ""); 
     final JMXConnector connector = JMXConnectorFactory.connect(target); 
     final MBeanServerConnection remote = connector.getMBeanServerConnection(); 

     final ObjectName memory = new ObjectName("java.lang:type=Memory"); 
     CompositeData cd = (CompositeData) remote.getAttribute(memory, "HeapMemoryUsage"); 

     final Long used = (Long) cd.get("used"); 
     System.out.println(used); 

    } 

    private static boolean pickThisOne(VirtualMachineDescriptor virtualMachineDescriptor) { 
     // TODO 
     return false; 
    } 
} 
+3

Nizza Probe, und man konnte auch ähnlich detailliertes Beispiel von hier der Agent und die lokale Adresse erhalten. Sie sollten die Methode 'virtualMachine.startLocalManagementAgent' verwenden. – ozhan

+1

Mit JDK 8, jetzt ist es viel einfacher zu verbinden zu laden: Scott Greenman familysearch.org –