[英]How to connect to JMX for JVM on local machine by pid (Java 9+)
[英]How to connect to a java program on localhost jvm using JMX?
我應該使用 JMX 連接到 localhost jvm 上的 java 程序。 換句話說,我想開發一個 JMX 客戶端來在本地主機上配置一個 java 程序。
不推薦使用 JConsole! JConsole 不適合,因為它是通用的 JMX 客戶端,對主程序性能有負面影響。
oracle 站點上的示例使用 RMIConnector 和 host:port 參數,但我不知道:應該在哪里設置 jmx 端口?
JConsole 可以選擇通過 PID 連接到 Java 進程。 但是我在 JMX api 中找不到任何將 PID 作為輸入參數的方法。
我們使用類似以下內容以編程方式連接到我們的 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();
}
我們還有一些代碼可以以編程方式將自身發布到 VM 參數之外的特定端口,但這比我想象的要復雜得多。
在“通過 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 服務器並將 bean 發布到遠程客戶端。
// 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)。
澄清一下,如果您只對獲取本地 JMX 統計信息感興趣,則不需要使用遠程 api。 只需使用java.lang.management.ManagementFactory
:
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
memoryMXBean.getHeapMemoryUsage().getMax();
...
List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans();
...
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;
}
這要求您在 JVM 啟動時為您嘗試讀取的進程使用 jmxremote 參數。 無需在啟動時傳遞 jmxremote 參數即可完成此操作。 您必須使用附加 api(僅適用於使用 Java 6 及更高版本的程序。
最簡單的意思:
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) ...
}
這是您如何通過其 PID 獲得到 Java 程序的 JMX 連接(僅適用於版本 <= Java 8):
import sun.management.ConnectorAddressLink;
import javax.management.*;
public static MBeanServerConnection getLocalJavaProcessMBeanServer(int javaProcessPID) throws IOException {
String address = ConnectorAddressLink.importFrom(javaProcessPID);
JMXServiceURL jmxUrl = new JMXServiceURL(address);
return JMXConnectorFactory.connect(jmxUrl).getMBeanServerConnection();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.