Как подключиться к java-программе на localhost jvm с помощью JMX? - PullRequest
40 голосов
/ 05 апреля 2011

Я должен подключиться к java-программе на localhost jvm, используя JMX.Другими словами, я хочу разработать клиент JMX для настройки java-программы на localhost.

  • Не рекомендую использовать JConsole!JConsole не подходит, потому что он является общим клиентом JMX и отрицательно влияет на производительность основной программы.

  • В примерах на сайте Oracle используется RMIConnector и параметры host: port, но я не знаю: гдедолжен установить порт jmx?

  • JConsole имеет возможность подключаться к процессам Java с помощью PID.Но я не нахожу в JMX api метода, в котором в качестве входного параметра указан PID.

Ответы [ 4 ]

63 голосов
/ 05 апреля 2011

Мы используем что-то вроде следующего для программного соединения с нашими серверами JMX. Вы должны запустить свой сервер с чем-то вроде следующих аргументов:

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

Для привязки к определенному адресу вам необходимо добавить следующие аргументы VM:

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

Затем вы можете подключиться к вашему серверу, используя код клиента JMX, как показано ниже:

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();
}

У нас также есть код, который может программно публиковать себя на конкретном порту вне аргументов виртуальной машины, но это больше, чем нужно, я думаю.


С точки зрения подключения "по pid", насколько я знаю, вам нужно использовать Java6, чтобы сделать это из земли Java. Я не использовал следующий код, но, похоже, он работает.

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();
    }
}

Я также являюсь автором пакета SimpleJMX , который позволяет легко запускать сервер JMX и публиковать компоненты для удаленных клиентов.

// 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();

Он также имеет клиентский интерфейс, но сейчас у него нет никаких механизмов для поиска процессов по PID - поддерживаются только комбинации хост / порт (в 6/2012).

4 голосов
/ 29 января 2013

Чтобы уточнить, если вы заинтересованы только в получении локальной статистики JMX, вам не нужно использовать удаленный API. Просто используйте java.lang.management.ManagementFactory:

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

List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans();
...
3 голосов
/ 28 декабря 2012
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;
}

Для этого требуется, чтобы вы использовали аргумент jmxremote при запуске JVM для процесса, который вы пытаетесь прочитать.Чтобы иметь возможность сделать это без необходимости передавать аргумент jmxremote при запуске.Вам нужно будет использовать приложение api (применимо только для Программ, использующих Java 6 и выше.

1 голос
/ 07 ноября 2016

Самое простое означает:

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) ...
}
...