Как программно вызвать операцию MBeans целевого процесса - PullRequest
0 голосов
/ 28 мая 2019

Я хочу смоделировать, что jconsole делает:

  1. Идентификация работающего процесса, который предоставляет функциональность jmx (например: pid: 14796 FreshProject.jar)

  2. Список доступных библиотек MBeans (например: org.jacoco)

  3. Вызов операции (например: нажатие dump)

MBeans Operation example

Я пытался использовать библиотеку simplejmx, как упомянуто здесь , но я не совсем понимаю, что hostName и port мне следуетиспользовать.Я попытался передать localhost и 1099, так как я прочитал, что это значения по умолчанию, но это ошибки java.net.ConnectException: Connection refused: connect.

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

Ответы [ 3 ]

1 голос
/ 28 мая 2019

Пожалуйста, проверьте ссылку - Как получить дамп потока и кучи Java-процесса в Windows, который не запущен в консоли , где я разместил ответ, в котором программная куча сбрасывается с помощью JMX& Отражение.Вы можете обратиться к программе в качестве образца.Этот код работает с JDK 6 и выше.

1 голос
/ 28 мая 2019

Я хочу смоделировать, что делает jconsole

Посмотрите на реализацию jconsole - см. http://openjdk.java.net/tools/svc/jconsole/ и https://github.com/openjdk/jdk/tree/master/src/jdk.jconsole/share/classes

Я не совсем понимаю, какое имя хоста и порт мне следует использовать. Я попытался передать localhost и 1099, так как я прочитал, что это значения по умолчанию, но это ошибки java.net.ConnectException: Соединение отказано: соединение.

Согласно https://docs.oracle.com/en/java/javase/11/management/monitoring-and-management-using-jmx-technology.html по умолчанию порт отсутствует. И JConsole использует Attach API - см. https://github.com/openjdk/jdk/blob/master/src/jdk.jconsole/share/classes/sun/tools/jconsole/LocalVirtualMachine.java В этом коде вы также найдете ответ на

Идентификация работающего процесса, который предоставляет функциональность jmx

Для подключения через порт необходимо указать соответствующие параметры. Например, следуя Example.java

class Example {
    public static void main(String[] args) {
        while (true) {
        }
    }
}

можно запустить как

java \
    -Dcom.sun.management.jmxremote.port=1099 \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Dcom.sun.management.jmxremote.ssl=false \
    Example

Тогда

Список доступных MBeans

можно сделать как

import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import java.lang.management.ManagementFactory;
import java.util.Iterator;
import java.util.Set;

class GetMBeans {
    public static void main(final String[] args) throws Exception {
       final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
       final JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
       final MBeanServerConnection connection = jmxc.getMBeanServerConnection();

       Set<ObjectInstance> instances = connection.queryMBeans(null, null);
       Iterator<ObjectInstance> iterator = instances.iterator();
       while (iterator.hasNext()) {
           ObjectInstance instance = iterator.next();
           System.out.println(instance.getClassName() + " " + instance.getObjectName());
       }
    }
}

После запуска вышеуказанного Example также с JaCoCo

java \
    -Dcom.sun.management.jmxremote.port=1099 \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Dcom.sun.management.jmxremote.ssl=false \
    -javaagent:jacoco-0.8.4/lib/jacocoagent.jar=jmx=true \
    Example

выполнение javac GetMBeans.java && java GetMBeans | grep jacoco производит

org.jacoco.agent.rt.internal_035b120.Agent org.jacoco:type=Runtime

Вызов операции

показано в документации JaCoCo - см. MBeanClient.java в https://www.jacoco.org/jacoco/trunk/doc/api.html

import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import java.lang.management.ManagementFactory;
import java.util.Iterator;
import java.util.Set;

class MBeanClient {
    public static void main(final String[] args) throws Exception {
       final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
       final JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
       final MBeanServerConnection connection = jmxc.getMBeanServerConnection();

       final IProxy proxy = (IProxy) MBeanServerInvocationHandler.newProxyInstance(connection, new ObjectName("org.jacoco:type=Runtime"), IProxy.class, false);

       final byte[] data = proxy.getExecutionData(false);
       System.out.println("Got " + data.length + " bytes");
    }

    public interface IProxy {
        String getVersion();
        String getSessionId();
        void setSessionId(String id);
        byte[] getExecutionData(boolean reset);
        void dump(boolean reset);
        void reset();
    }
}

исполнение javac MBeanClient.java && java MBeanClient производит

Got 84 bytes
0 голосов
/ 28 мая 2019

Я не пробовал версию @ Godin, но я уверен, что она работает, поскольку она очень подробная.

Я сделал это по-другому: я использовал библиотеку simplejmx, доступную на https://jar -download.com /? Search_box = simplejmx .

Чтобы присоединить JmxClient к процессу, вам нужно знать порт, на котором он запущен.Его можно установить с помощью аргументов JVM следующим образом:

-Dcom.sun.management.jmxremote.port=1240
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

После запуска приложения на указанном порту следующий скрипт получит к нему доступ и вызовет целевую операцию:

public static void main(String[] args) throws Exception {
    JmxClient client = new JmxClient("localhost", 1240);
    client.invokeOperation(new ObjectName("org.jacoco:type=Runtime"), "dump", new Object[] {true});
    client.close();
}

Также проверьте: Как программно проверить операции и атрибуты JMX MBean?

Примечание: он должен быть на jdk версии 10 или выше.Не работает на 8.

...