2011-04-05 16 views
35

Debería conectarme a un programa java en localhost jvm usando JMX. En otras palabras, quiero desarrollar un cliente JMX para configurar un programa Java en localhost.Cómo conectarse a un programa Java en localhost jvm usando JMX?

  • ¡No recomiendo usar JConsole! JConsole no es adecuado porque es un cliente JMX general y tiene un efecto negativo en el rendimiento del programa principal.

  • Muestras en el sitio oracle uso RMIConnector y host: parámetros del puerto pero no sé: ¿dónde debería establecer el puerto jmx?

  • JConsole tiene una opción para conectarse a los procesos Java por PID. Pero no encuentro ningún método en JMX api que tenga PID como parámetro de entrada.

+1

Tanto el principal cliente del programa y jmx son programas autónomos (Java sE). – mjafari

+0

También vea http://www.pongasoft.com/blog/yan/entry/connecting_to_a_local_vm/ –

Respuesta

56

Utilizamos algo como lo siguiente para conectar programáticamente a nuestros servidores JMX. Debe ejecutar el servidor con algo parecido a los siguientes argumentos:

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

para unirse a una dirección en particular tendrá que añadir los siguientes argumentos de VM:

-Djava.rmi.server.hostname=A.B.C.D 

A continuación, puede conectarse a su servidor utilizando código de cliente JMX como la siguiente:

String host = "localhost"; // or some A.B.C.D 
int port = 1234; 
String url = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi"; 
JMXServiceURL serviceUrl = new JMXServiceURL(url); 
JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceUrl, null); 
try { 
    MBeanServerConnection mbeanConn = jmxConnector.getMBeanServerConnection(); 
    // now query to get the beans or whatever 
    Set<ObjectName> beanSet = mbeanConn.queryNames(null, null); 
    ... 
} finally { 
    jmxConnector.close(); 
} 

también tenemos el código que puede publicar mediante programación en sí a un puerto en particular fuera de los argumentos de VM pero eso es más fu de lo que necesitas, creo.


En cuanto a la conexión "por pid", tiene que estar usando java6 hacerlo desde la tierra de Java por lo que yo sé. No he usado el siguiente código, pero parece que funciona.

List<VirtualMachineDescriptor> vms = VirtualMachine.list(); 
for (VirtualMachineDescriptor desc : vms) { 
    VirtualMachine vm; 
    try { 
     vm = VirtualMachine.attach(desc); 
    } catch (AttachNotSupportedException e) { 
     continue; 
    } 
    Properties props = vm.getAgentProperties(); 
    String connectorAddress = 
     props.getProperty("com.sun.management.jmxremote.localConnectorAddress"); 
    if (connectorAddress == null) { 
     continue; 
    } 
    JMXServiceURL url = new JMXServiceURL(connectorAddress); 
    JMXConnector connector = JMXConnectorFactory.connect(url); 
    try { 
     MBeanServerConnection mbeanConn = connector.getMBeanServerConnection(); 
     Set<ObjectName> beanSet = mbeanConn.queryNames(null, null); 
     ... 
    } finally { 
     jmxConnector.close(); 
    } 
} 

He también el autor de SimpleJMX package que hace que sea fácil de iniciar un servidor JMX y publicar los granos a los clientes remotos.

// create a new server listening on port 8000 
JmxServer jmxServer = new JmxServer(8000); 
// start our server 
jmxServer.start(); 
// register our lookupCache object defined below 
jmxServer.register(lookupCache); 
jmxServer.register(someOtherObject); 
// stop our server 
jmxServer.stop(); 

Se tiene una interfaz de cliente así pero en este momento no tiene ningún mecanismo para encontrar procesos de PID - combinaciones único huésped/puertos son compatibles (en 6/2012).

+1

¡Gracias Gray! ¿Puede usted (u otras personas) responder mi segunda pregunta (conexión jmx local usando PID)? – mjafari

+0

Si por algún motivo ConnectorAddress es nulo, puede intentar cargar el agente dinámicamente. Consulte http://www.pongasoft.com/blog/yan/entry/connecting_to_a_local_vm/ –

+0

tiene un problema de compilación en la línea: jmxConnector.close(); – shlomi33

3
List<VirtualMachineDescriptor> vm = new ArrayList<VirtualMachineDescriptor>(); 
     jvmList = new JVMListManager(); 

     vm = jvmList.listActiveVM(); 

     for (VirtualMachineDescriptor vmD : vm) 
     { 
      try 
      { 

      //importFrom is taking a process ID and returning a service url in a String Format 
      String ServiceUrl = ConnectorAddressLink.importFrom(Integer.parseInt(vmD.id().trim())); 
      JMXServiceURL jmxServiceUrl = new JMXServiceURL(ServiceUrl); 

      jmxConnector = JMXConnectorFactory.connect(jmxServiceUrl, null); 
      con = jmxConnector.getMBeanServerConnection(); 
      CompilationMXBean compMXBean = ManagementFactory.newPlatformMXBeanProxy(con 
        , ManagementFactory.COMPILATION_MXBEAN_NAME 
        , CompilationMXBean.class); 
      }catch(Exception e) 
      { 
      //Do Something 
      } 
     } 


protected List listActiveVM() { 
    List<VirtualMachineDescriptor> vm = VirtualMachine.list(); 

    return vm; 
} 

Esto requiere que utilice el argumento jmxremote en el inicio de JVM para el proceso que está tratando de leer. PARA poder hacerlo sin tener que pasar un argumento jmxremote al inicio. Deberá utilizar la aplicación adjunta (solo aplicable para Programas que utilicen Java 6 y superior.

4

Para aclarar, si solo está interesado en obtener estadísticas locales de JMX, no necesita usar la API remota. Simplemente use java.lang.management.ManagementFactory:

MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); 
memoryMXBean.getHeapMemoryUsage().getMax(); 
... 

List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans(); 
... 
1

medio más simple:

import javax.management.Attribute; 
import javax.management.AttributeList; 
import java.lang.management.ManagementFactory; 
import javax.management.MBeanServer; 
import javax.management.ObjectName; 

// set a self JMX connection 
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); 
// set the object name(s) you are willing to query, here a CAMEL JMX object 
ObjectName objn = new ObjectName("org.apache.camel:context=*,type=routes,name=\"route*\""); 
Set<ObjectName> objectInstanceNames = mBeanServer.queryNames(objn, null); 
for (ObjectName on : objectInstanceNames) { 
    // query a number of attributes at once 
    AttributeList attrs = mBeanServer.getAttributes(on, new String[] {"ExchangesCompleted","ExchangesFailed"}); 
    // process attribute values (beware of nulls...) 
    // ... attrs.get(0) ... attrs.get(1) ... 
} 
Cuestiones relacionadas