|
|
A small program that prints the attributes of all JVM MBeans |
A few weeks ago I blogged about how to programmatically access
the JVM Monitoring information. Here is a small Java application
that prints all the
attributes of all the JVM Management & Monitoring MBeans.
The sample simply prints the attributes of the JVM MBeans from the
JVM in which it runs. It would be very easy to make it print the
information of a remote JVM. You would just need to copy the code
from the JVMRuntimeClient shown in my previous blog:
public static void main(String[] args) throws Exception {
// Parse arguments.
final ConnectionArgs cArgs = new ConnectionArgs(args);
// Get target's URL
final JMXServiceURL target = cArgs.getJMXServiceURL();
// Connect to target (assuming no security)
final JMXConnector connector = JMXConnectorFactory.connect(target);
// Get an MBeanServerConnection on the remote VM.
final MBeanServerConnection remote =
connector.getMBeanServerConnection();
displayAll(conn,new ObjectName("java.lang:*"));
}
|
This sample is composed of 4 small classes:
-
TextDataDisplay.java: displays
attribute values as text.
Uses a property-like syntax to display complex values, such as
CompositeData, TabularData, Map, Collection, and array of thoses.
-
MBeanDataDisplay.java: displays
all attributes of a given MBean.
Uses TextDataDisplay to display
individual values.
-
JVMMBeanDataDisplay.java:
extends MBeanDataDisplay, and implements
a special case for displaying ThreadMXBean attributes. This is
a custom MBeanDataDisplay that has some special knowledge of the
JVM MBeans. In particular, for the ThreadMXBean, instead of
simply displaying the value of the attribute "AllThreadIds" (an
array of longs) it gets and displays the corresponding ThreadInfo
for each Thread ID.
-
Main.java: implements the displayAll() method.
Here is a small extract of what the program prints:
************************************************************
MBean: java.lang:type=Memory
{
# HeapMemoryUsage
HeapMemoryUsage=CompositeData(java.lang.management.MemoryUsage)
{
HeapMemoryUsage.committed=132644864
HeapMemoryUsage.init=134217728
HeapMemoryUsage.max=957743104
HeapMemoryUsage.used=692080
}
# NonHeapMemoryUsage
NonHeapMemoryUsage=CompositeData(java.lang.management.MemoryUsage)
{
NonHeapMemoryUsage.committed=18350080
NonHeapMemoryUsage.init=18350080
NonHeapMemoryUsage.max=100663296
NonHeapMemoryUsage.used=3245944
}
# ObjectPendingFinalizationCount
ObjectPendingFinalizationCount=0
# Verbose
Verbose=false
}
************************************************************
MBean: java.lang:type=GarbageCollector,name=PS MarkSweep
{
# CollectionCount
CollectionCount=0
# CollectionTime
CollectionTime=0
# LastGcInfo
LastGcInfo=null
# MemoryPoolNames
MemoryPoolNames[0]=PS Eden Space
MemoryPoolNames[1]=PS Survivor Space
MemoryPoolNames[2]=PS Old Gen
MemoryPoolNames[3]=PS Perm Gen
# Name
Name=PS MarkSweep
# Valid
Valid=true
}
************************************************************
|
Feel free to experiment with this and to invent your own way of displaying
the attribute values!
Update: See also Sundar's blog on how to programmatically dump heap from Java applications.
package opentextdisplay;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.logging.Logger;
import javax.management.JMException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
public class Main {
private static final Logger LOG =
Logger.getLogger(Main.class.getName());
public final static String separator =
"\n************************************************************\n";
public static void displayAll(MBeanServerConnection conn,
ObjectName pattern) throws IOException, JMException {
final JVMMBeanDataDisplay display = new JVMMBeanDataDisplay(conn);
System.out.println(separator);
for (ObjectName mbean : conn.queryNames(pattern,null)) {
System.out.println(display.toString(mbean));
System.out.println(separator);
}
}
public Main() {
}
public static void main(String[] args) throws Exception {
final MBeanServerConnection conn =
ManagementFactory.getPlatformMBeanServer();
displayAll(conn,new ObjectName("java.lang:*"));
}
}
|
package opentextdisplay;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
public class TextDataDisplay {
private static final Logger LOG =
Logger.getLogger(TextDataDisplay.class.getName());
public TextDataDisplay() {
}
public String display(String name, Object data) {
return display("",name,data);
}
public String display(String prefix, String name, Object data) {
if (name == null)
throw new IllegalArgumentException("name must not be null");
final StringBuffer buffer = new StringBuffer();
return write(buffer,"",name,data).toString();
}
public StringBuffer write(StringBuffer buffer, String prefix,
String name, Object data) {
if (data == null) return writeSimple(buffer,prefix,name,null,true);
if (data.getClass().isArray())
return writeArray(buffer,prefix,name,data);
if (data instanceof CompositeData)
return writeCompositeData(buffer,prefix,name,(CompositeData)data);
if (data instanceof TabularData)
return writeTabularData(buffer,prefix,name,(TabularData)data);
if (data instanceof Map)
return writeMap(buffer,prefix,name,(Map)data);
if (data instanceof Collection) {
return writeArray(buffer,prefix,name,((Collection)data).toArray());
}
return writeSimple(buffer,prefix,name,data,true);
}
String toString(Object data) {
if (data==null) return "null";
else return data.toString();
}
StringBuffer writeSimple(StringBuffer buffer, String prefix,
String name, Object data, boolean writeline) {
buffer.append(prefix).append(name).append("=").append(toString(data));
if (writeline) buffer.append("\n");
return buffer;
}
StringBuffer writeArray(StringBuffer buffer, String prefix,
String name, Object array) {
if (array == null)
return writeSimple(buffer,prefix,name,null,true);
final int length = Array.getLength(array);
for (int i=0;i<length;i++) {
final Object data = Array.get(array,i);
write(buffer,prefix,name+"["+i+"]",data);
}
return buffer;
}
StringBuffer writeCompositeData(StringBuffer buffer,
String prefix, String name, CompositeData data) {
if (data == null)
return writeSimple(buffer,prefix,name,null,true);
writeSimple(buffer,prefix,name,"CompositeData("+
data.getCompositeType().getTypeName()+")",true);
buffer.append(prefix).append("{").append("\n");
final String fieldprefix = prefix + " ";
for (String key : data.getCompositeType().keySet()) {
write(buffer,fieldprefix,name+"."+key,data.get(key));
}
buffer.append(prefix).append("}").append("\n");
return buffer;
}
StringBuffer writeTabularData(StringBuffer buffer,
String prefix, String name, TabularData data) {
if (data == null)
return writeSimple(buffer,prefix,name,null,true);
writeSimple(buffer,prefix,name,"TabularData("+
data.getTabularType().getTypeName()+")",true);
final List<String> keyNames = data.getTabularType().getIndexNames();
final int indexCount = keyNames.size();
for (Object keys : data.keySet()) {
final Object[] keyValues = ((List<?>)keys).toArray();
final StringBuilder b = new StringBuilder(name);
b.append("[");
for (int i=0;i<indexCount;i++) {
if (i>0) b.append(", ");
b.append(keyNames.get(i)+"="+keyValues[i]);
}
b.append("]");
writeCompositeData(buffer,prefix,b.toString(),data.get(keyValues));
b.append("\n");
}
return buffer;
}
StringBuffer writeMap(StringBuffer buffer,
String prefix, String name, Map<Object,Object> data) {
if (data == null)
return writeSimple(buffer,prefix,name,null,true);
writeSimple(buffer,prefix,name,"java.util.Map",true);
for (Entry<Object,Object> e : data.entrySet()) {
write(buffer,prefix,name+"["+e.getKey()+"]",e.getValue());
}
return buffer;
}
}
|
package opentextdisplay;
import java.io.IOException;
import java.util.logging.Logger;
import javax.management.JMException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
public class MBeanDataDisplay {
private static final Logger LOG =
Logger.getLogger(MBeanDataDisplay.class.getName());
final MBeanServerConnection server;
final TextDataDisplay dataDisplay = new TextDataDisplay();
public MBeanDataDisplay(MBeanServerConnection conn) {
this.server = conn;
}
StringBuffer writeAttribute(StringBuffer buffer,
String prefix, ObjectName mbean,
MBeanAttributeInfo info, Object value) {
buffer.append(prefix).append("# ").append(info.getDescription())
.append("\n");
return dataDisplay.write(buffer,prefix,info.getName(),value);
}
public StringBuffer write(StringBuffer buffer, String prefix, ObjectName mbean)
throws IOException, JMException {
final MBeanInfo info = server.getMBeanInfo(mbean);
buffer.append(prefix).append("MBean: ").append(mbean).append("\n");
buffer.append(prefix).append("{\n");
final String attrPrefix = prefix+" ";
final MBeanAttributeInfo[] attributes = info.getAttributes();
for (MBeanAttributeInfo attr : attributes) {
Object toWrite = null;
try {
toWrite = server.getAttribute(mbean,attr.getName());
} catch (Exception x) {
toWrite = x;
}
writeAttribute(buffer,attrPrefix,mbean,attr,toWrite);
buffer.append("\n");
}
buffer.append(prefix).append("}\n");
return buffer;
}
public String toString(String prefix, ObjectName mbean)
throws IOException, JMException {
return write(new StringBuffer(),prefix,mbean).toString();
}
public String toString(ObjectName mbean)
throws IOException, JMException {
return toString("",mbean);
}
}
|
package opentextdisplay;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.logging.Logger;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
public class JVMMBeanDataDisplay extends MBeanDataDisplay {
private static final Logger LOG =
Logger.getLogger(JVMMBeanDataDisplay.class.getName());
private final static ObjectName THREAD_MXBEAN_NAME;
static {
try {
THREAD_MXBEAN_NAME =
new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME);
} catch (Exception x) {
throw new ExceptionInInitializerError(x);
}
}
public JVMMBeanDataDisplay(MBeanServerConnection conn) {
super(conn);
}
@Override
StringBuffer writeAttribute(StringBuffer buffer,
String prefix, ObjectName mbean,
MBeanAttributeInfo info, Object value) {
if (THREAD_MXBEAN_NAME.equals(mbean) &&
info.getName().equals("AllThreadIds")) {
final Object threadInfos;
try {
threadInfos = server.invoke(mbean,"getThreadInfo",
new Object[] { value, 1 },
new String[] { long[].class.getName(),
int.class.getName() });
} catch (Exception ex) {
throw new IllegalArgumentException(mbean.toString(),ex);
}
buffer.append(prefix).append("# ").append("AllThreadInfo")
.append("\n");
return dataDisplay.write(buffer,prefix,"AllThreadInfo",
threadInfos);
} else {
return super.writeAttribute(buffer,prefix,mbean,info,value);
}
}
}
|
Tags:
java
jmx
jvm
monitoring
Posted by dfuchs
( May 04 2007, 06:39:28 PM CEST )
Permalink
|
very very nice blog now i'm gona adopt your code to show graph in a new swing application
Posted by nizar on April 19, 2009 at 07:20 PM CEST #
can i get your code please and integrate it into my projecT?
Posted by nizar on April 19, 2009 at 07:24 PM CEST #