如何以编程方式调用目标进程的MBean操作
How to programmatically invoke MBeans operation of target process
我想通过以下方式模拟 jconsole
的作用:
识别公开 jmx 功能的 运行 进程(例如:pid: 14796 FreshProject.jar
)
列出可用的 MBean 库(例如:org.jacoco
)
调用操作(例如:单击 dump
)
我试过使用 simplejmx
库 here 但我对应该使用什么 hostName
和 port
感到困惑。我尝试传递 localhost
和 1099
因为我读过这些是默认值但它出错 java.net.ConnectException: Connection refused: connect
.
请不要将我指向其他软件 post 并关闭它,因为我很可能已经阅读并尝试过几次。
I want to simulate what jconsole does
查看 jconsole 的实现 - 参见 http://openjdk.java.net/tools/svc/jconsole/ and https://github.com/openjdk/jdk/tree/master/src/jdk.jconsole/share/classes
I am confused as to what hostName and port I should use. I tried passing localhost and 1099 as I've read these are the default values but it errors java.net.ConnectException: Connection refused: connect.
根据 https://docs.oracle.com/en/java/javase/11/management/monitoring-and-management-using-jmx-technology.html by default there is no port. And JConsole uses Attach API - see https://github.com/openjdk/jdk/blob/master/src/jdk.jconsole/share/classes/sun/tools/jconsole/LocalVirtualMachine.java 在此代码中,您还可以在
上找到答案
Identifying a running process that exposes jmx functionality
要通过端口连接,您需要指定适当的参数。例如以下 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
然后
Listing the available 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
Invoking an operation
显示在 JaCoCo 文档中 - 请参阅 MBeanClient.java
at 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
我没有尝试@Godin 的版本,但我确信它可以工作,因为它非常详细。
我用了不同的方法:我使用了 https://jar-download.com/?search_box=simplejmx 上的 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();
}
同时检查:How to programmatically check JMX MBean operations and attributes?
注意:它必须在 jdk 版本 10 或更高版本上。不适用于 8。
请检查 link - How to get a thread and heap dump of a Java process on Windows that's not running in a console ,我在其中发布了一个答案,其中通过使用 JMX 和反射以编程方式转储堆。您可以将该程序作为示例参考。此代码从 JDK 6 开始有效。
我想通过以下方式模拟 jconsole
的作用:
识别公开 jmx 功能的 运行 进程(例如:
pid: 14796 FreshProject.jar
)列出可用的 MBean 库(例如:
org.jacoco
)调用操作(例如:单击
dump
)
我试过使用 simplejmx
库 here 但我对应该使用什么 hostName
和 port
感到困惑。我尝试传递 localhost
和 1099
因为我读过这些是默认值但它出错 java.net.ConnectException: Connection refused: connect
.
请不要将我指向其他软件 post 并关闭它,因为我很可能已经阅读并尝试过几次。
I want to simulate what jconsole does
查看 jconsole 的实现 - 参见 http://openjdk.java.net/tools/svc/jconsole/ and https://github.com/openjdk/jdk/tree/master/src/jdk.jconsole/share/classes
I am confused as to what hostName and port I should use. I tried passing localhost and 1099 as I've read these are the default values but it errors java.net.ConnectException: Connection refused: connect.
根据 https://docs.oracle.com/en/java/javase/11/management/monitoring-and-management-using-jmx-technology.html by default there is no port. And JConsole uses Attach API - see https://github.com/openjdk/jdk/blob/master/src/jdk.jconsole/share/classes/sun/tools/jconsole/LocalVirtualMachine.java 在此代码中,您还可以在
上找到答案Identifying a running process that exposes jmx functionality
要通过端口连接,您需要指定适当的参数。例如以下 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
然后
Listing the available 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
Invoking an operation
显示在 JaCoCo 文档中 - 请参阅 MBeanClient.java
at 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
我没有尝试@Godin 的版本,但我确信它可以工作,因为它非常详细。
我用了不同的方法:我使用了 https://jar-download.com/?search_box=simplejmx 上的 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();
}
同时检查:How to programmatically check JMX MBean operations and attributes?
注意:它必须在 jdk 版本 10 或更高版本上。不适用于 8。
请检查 link - How to get a thread and heap dump of a Java process on Windows that's not running in a console ,我在其中发布了一个答案,其中通过使用 JMX 和反射以编程方式转储堆。您可以将该程序作为示例参考。此代码从 JDK 6 开始有效。