JMX is a way to view and manipulate the runtime state of your application. It's somewhat similar in concept to SNMP, if that helps. IMO, it's indispensable for monitoring and understanding server-type applications that might not have any other user interface besides writing to a log file.
The basic approach is to create an interface for the things you want to monitor, then have a class implement the interface, then register an instance of that class with the "MBeanServer" (which actually makes the stuff defined in the interface available to JMX monitoring apps like jconsole).
Here's a trivial -- but working -- example:
(I'm assuming Java 5 or better)
TestServerMBean.java
public interface TestServerMBean
{
public long getUptimeMillis();
public long getFooCount();
public void setFooCount(long val);
public void printStuff(String stuff);
}
TestServer.java:
import java.lang.management.ManagementFactory;
import java.util.concurrent.atomic.AtomicLong;
import javax.management.ObjectName;
// If jconsole doesn't see this app automatically, invoke the application with the following java flags, and connect
// 'remotely' via jconsole.
//
// -Dcom.sun.management.jmxremote
// -Dcom.sun.management.jmxremote.port=2222 (or whatever)
// -Dcom.sun.management.jmxremote.authenticate=false
// -Dcom.sun.management.jmxremote.ssl=false
public class TestServer implements TestServerMBean
{
private final AtomicLong m_counter = new AtomicLong(0L);
private final long m_startTimeMillis = System.currentTimeMillis();
public void run() throws InterruptedException {
while (true) {
m_counter.incrementAndGet();
Thread.sleep(5000);
}
}
public long getFooCount() {
return m_counter.get();
}
public void setFooCount(long val) {
m_counter.set(val);
}
public long getUptimeMillis() {
return System.currentTimeMillis() - m_startTimeMillis;
}
public void printStuff(String stuff) {
System.out.println(stuff);
}
public static void main(String[] args) throws Exception {
TestServer ts = new TestServer();
ManagementFactory.getPlatformMBeanServer().registerMBean(ts, new ObjectName("myapp:service=MyServer"));
ts.run();
}
}
Compile and run TestServer.class as usual, fire up jconsole
, connect to TestServer (it'll show up automatically, else see comments in code above), then look at the 'MBeans' tab, and you'll see our instance named myapp:service=MyServer
. You can view the current "uptime", and watch FooCounter
increment every 5 seconds. You can also set FooCounter to whatever (long) value you want, and invoke the printStuff
method with any String argument.
Obviously this is a ridiculous "server", but hopefully having a simple working example will help illustrate the overall concept: being able to peek into and manipulate a running app.
There are a lot of additional features and different types of MBeans, but just the vanilla JMX shown above goes a long way, IMO.