我应该使用JMX连接到localhostjvm上的java程序。换句话说,我想开发一个JMX客户端来在localhost上配置java程序。
-
不建议使用JConsole!JConsole不适合,因为它是通用的JMX客户端,对主程序的性能有负面影响。
-
oracle站点上的示例使用RMIConnector和host:port params,但我不知道:jmx端口应该设置在哪里?
-
JConsole有一个通过PID连接到java进程的选项。但我在JMXAPI中找不到任何将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查找进程——只支持主机/端口组合(2012年6月(。
要澄清的是,如果您只对获取本地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 8(获得与Java程序的JMX连接的方法:
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();
}