问题
I am running a client/server application using JBoss.
How can I connect to the server JVM's MBeanServer? I want to use the MemoryMX MBean to track the memory consumption.
I can connect to the JBoss MBeanServer using JNDI lookup but the java.lang.MemoryMX MBean is not registered with the JBoss MBeanServer.
EDIT: The requirement is for programmatic access to the memory usage from the client.
回答1:
Unlike the JBoss server's MBeanServer, the JVM's MBean server doesn't allow remote monitoring by default. You need to set various system properties to allow that:
http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html
回答2:
I wrote a class like this:
import javax.management.remote.JMXServiceURL;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
public class JVMRuntimeClient
{
static void main(String[] args) throws Exception
{
if (args == null)
{
System.out.println("Usage: java JVMRuntimeClient HOST PORT");
}
if(args.length < 2)
{
System.out.println("Usage: java JVMRuntimeClient HOST PORT");
}
try
{
JMXServiceURL target = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"+args[0]+":"+args[1]+"/jmxrmi");
JMXConnector connector = JMXConnectorFactory.connect(target);
MBeanServerConnection remote = connector.getMBeanServerConnection();
/**
* this is the part where you MUST know which MBean to get
* com.digitalscripter.search.statistics:name=requestStatistics,type=RequestStatistics
* YOURS WILL VARY!
*/
ObjectName bean = new ObjectName("com.digitalscripter.search.statistics:name=requestStatistics,type=RequestStatistics");
MBeanInfo info = remote.getMBeanInfo(bean);
MBeanAttributeInfo[] attributes = info.getAttributes();
for (MBeanAttributeInfo attr : attributes)
{
System.out.println(attr.getDescription() + " " + remote.getAttribute(bean,attr.getName()));
}
connector.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
System.exit(0);
}
}
}
回答3:
A code example from an IBM article: link
MBeanServerConnection serverConn;
try {
//connect to a remote VM using JMX RMI
JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://<addr>");
JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
serverConn = jmxConnector.getMBeanServerConnection();
ObjectName objName = new
ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
// Get standard attribute "VmVendor"
String vendor =
(String) serverConn.getAttribute(objName, "VmVendor");
} catch (...) { }
回答4:
Have you tried launching a JConsole
(is $JAVA_HOME/bin
) to connect with the server? You should be able to view memory stats from there
回答5:
The following code lists all mbeans of a given (jmx enabled) java application with their attributes and operations grouped by the domain. Just start the java app you wanna monitor with a fixed jmx port, e.g. by using these vm parameters:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9000
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
Then run this main:
import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
public class JmxListAll {
public static void main(String[] args) throws IOException, MalformedObjectNameException, IntrospectionException, InstanceNotFoundException, ReflectionException {
/*
1. JMXServiceURL.
*/
String jmxHost = "localhost:9000"; // exactly like jconsole localhost:9026
String url = "service:jmx:rmi:///jndi/rmi://" + jmxHost + "/jmxrmi";
JMXServiceURL serviceURL = new JMXServiceURL(url);
/*
2. JMXConnector and the actual serverConnection
*/
JMXConnector connector = JMXConnectorFactory.connect(serviceURL);
MBeanServerConnection serverConnection = connector.getMBeanServerConnection();
/*
3. Walk through the domains and their objects
*/
System.out.println("\n Now we have a look at " + serverConnection.getMBeanCount() + " mbeans!");
int objectCount = 0;
for (String domain : serverConnection.getDomains()) {
System.out.println("\n***********************************************************************************");
System.out.println("DOMAIN: " + domain);
// query all the beans for this domain using a wildcard filter
for (ObjectName objectName : serverConnection.queryNames(new ObjectName(domain + ":*"), null)) {
System.out.println(" objectName " + ++objectCount + ": " + objectName);
MBeanInfo info = serverConnection.getMBeanInfo(objectName);
for (MBeanAttributeInfo attr : info.getAttributes()) {
System.out.print(" attr: " + attr.getDescription());
try {
String val = serverConnection.getAttribute(objectName, attr.getName()).toString();
System.out.println(" -> " + abbreviate(val));
} catch (Exception e) {
System.out.println(" FAILED: " + e);
}
}
for (MBeanOperationInfo op : info.getOperations()) {
System.out.println(" op: " + op.getName());
}
}
}
}
static String abbreviate(String text) {
if (text != null && text.length() > 42) {
return text.substring(0, 42) + "...";
} else {
return text;
}
}
}
As you should see, in the java.lang domain are several memory related mbeans. Pick the one you need.
来源:https://stackoverflow.com/questions/1270173/accessing-a-remote-mbean-server