How to programmatically check JMX MBean operations

2019-03-11 17:39发布

问题:

Suppose we have a MBean that has the following attributes and operations.

Attributes: name size

Operations: getName() getSize()

Is there a way to programmatically check for the attributes and operations? I've been working with the IBM WebSphere MBeans and their documentation isn't very good.

For example, if you go to IBMs Infocenter and navigate to Network Deployment -> Reference -> Programming interfaces -> Mbean interfaces -> ThreadPool. They only have attributes listed and no operations.

Using the WebSphere wsadmin tool, I can actually check to see the operations and attributes. I'd like to know if there's a way to do this with all MBeans.

wsadmin>print Help.attributes(object)
Attribute                       Type                            Access
name                            java.lang.String                RO
maximumSize                     int                             RW
minimumSize                     int                             RW
inactivityTimeout               long                            RW
growable                        boolean                         RW
stats                           javax.management.j2ee.statistics.Stats  RO

wsadmin>print Help.operations(object)
Operation
java.lang.String getName()
int getMaximumPoolSize()
void setMaximumPoolSize(int)
int getMinimumPoolSize()
void setMinimumPoolSize(int)
long getKeepAliveTime()
void setKeepAliveTime(long)
boolean isGrowAsNeeded()
void setGrowAsNeeded(boolean)
javax.management.j2ee.statistics.Stats getStats()

回答1:

I can't quite tell if you are talking about programmatically finding the MBeans from inside the current JVM or remotely from a client. There are a number of JMX client libraries. The one I wrote is available here:

http://256stuff.com/sources/simplejmx/

With my code you can do something like:

JmxClient client = new JmxClient(hostName, port);
Set<ObjectName> objectNames = getBeanNames() 
for (ObjectName name : objectNames) {
    MBeanAttributeInfo[] attributes = getAttributesInfo(name);
    MBeanOperationInfo[] operations = getOperationsInfo(name);
}

If you are asking about the current JVM then you should be able to get bean information from the internal beans this way:

MBeanServer server = ManagementFactory.getPlatformMBeanServer();
Set<ObjectName> objectNames = server.queryNames(null, null);
for (ObjectName name : objectNames) {
    MBeanInfo info = server.getMBeanInfo(name);
}


回答2:

Here is an example with simple JMX for ActiveMQ. Can be useful for someone in future with just replacing activeMQ values:

String brokerName = "AMQBroker";
String username = "";
String password = "";
String hostname = "localhost";
int port = 1099;

Map<String, Object> env = new HashMap<String, Object>();
if (username != null || password != null) {
    String[] credentials = new String[] { username, password };
    env.put("jmx.remote.credentials", credentials);
}

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + hostname + ":" + port + "/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
MBeanServerConnection conn = jmxc.getMBeanServerConnection();

// here is example for Type=Broker, can be different like
// "org.apache.activemq:BrokerName=" + brokerName + ",Type=Connection,ConnectorName=openwire,Connection=*"
// "org.apache.activemq:BrokerName=" + brokerName + ",*,Type=NetworkBridge" or same for Queue, Topic, Subscription
ObjectName name = new ObjectName("org.apache.activemq:BrokerName=" + brokerName + ",Type=Broker");
Set<ObjectName> queryNames = conn.queryNames(name, null);
// here is set with one element, but can be more depending on ObjectName query
for (ObjectName objectName : queryNames) {
    System.out.println(objectName.getCanonicalName());
    // use attribute you can be interested in
    System.out.println(conn.getAttribute(objectName, "Slave"));
}