Подтвердить что ты не робот

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

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

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

  • Образцы на сайте oracle используют RMIConnector и host: параметры порта, но я не знаю: где должен быть установлен порт jmx?

  • JConsole имеет возможность подключаться к java-процессам с помощью PID. Но я не нашел в JMX api метода, который имеет ПИД в качестве входного параметра.

4b9b3361

Ответ 1

Для программного подключения к нашим серверам 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();
}

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


С точки зрения подключения "по 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-сервера и публикацию beans для удаленных клиентов.

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

Ответ 2

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

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

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

Ответ 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;
}

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

Ответ 4

Простейшее означает:

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