Oddjob 1.2 New Features – Part 4

In New Features Part 1, I mentioned that one of the biggest impediments to a release was the urge to implement that one last killer feature. Well I’m weak – I caved, I did another feature.

JMX With Oddjob

The new feature is the ability to get and set attributes and invoke operations of remote MBeans from within Oddjob.

Oddjob already uses JMX to monitor remote Oddjobs, but its <jmx:client> creates Dynamic Proxies using a bunch of JMX notifications and operations to hide the complexity of the server and make everything ‘appear’ as if it is on your desktop. Until now there was no way to do simple JMX stuff using Oddjob’s built in JMX support.

What has been added is a new <jmx:service>. Here it is being used by Oddjob to monitor a process with a memory leak.

JMX Memory Monitor
The JMX Service exposes JMX Domains and MBeans as Oddjob friendly components, and adds them to Oddjob’s Job Tree so they are visible in Oddjob Explorer. In the screen shot I’ve expanded the tree and we can see the domains with folder icons, and the MBeans for the java.lang domain. Although not visible here, the Properties panel for an MBean shows the values of the MBeans Attributes and the Log Panel displays a Dump of the MBeanInfo and the results of any operation invocations on the MBean. This view of the MBeans is intended to be diagnostic only – The JMX Service is not intended for human interaction, we have JConsole for that.

The Properties panel we see above is for the Variables job. It shows the value of a variable called mem that is being populated from an MBean attribute.

We can see how in the configuration:

<oddjob>
  <job>
    <sequential>
      <jobs>
        <jmx:service connection="localhost:2012" id="jmx-monitor"
          xmlns:jmx="http://rgordon.co.uk/oddjob/jmx" />
        <scheduling:timer xmlns:scheduling="http://rgordon.co.uk/oddjob/scheduling">
          <schedule>
            <schedules:interval interval="00:00:15"
              xmlns:schedules="http://rgordon.co.uk/oddjob/schedules" />
          </schedule>
          <job>
            <sequential>
              <jobs>
                <variables id="vars">
                  <mem>
                    <value
                      value="${jmx-monitor/&quot;java.lang:type=Memory&quot;.HeapMemoryUsage.used}" />
                  </mem>
                </variables>
                <check gt="41943040" value="${vars.mem}" />
                <invoke function="gc">
                  <source>
                    <value
                      value="${jmx-monitor/&quot;java.lang:type=Memory&quot;}" />
                  </source>
                </invoke>
              </jobs>
            </sequential>
          </job>
        </scheduling:timer>
      </jobs>
    </sequential>
  </job>
</oddjob>

Notice how the JMX Service has been given the id jmx-monitor. The MBeans are referable using expressions of the form ${jmx-monitor/Object Name}. We see this in the Variables job and the Invoke job – but I’m jumping ahead. Let’s explain what the monitor does.

A timer runs a sequence of 3 jobs every 15 seconds.

  1. The Variables job is re-populated with the value of the used key of the HeapMemoryUsage CompositeData attribute of the Memory MBean. The XML escaping obfiscates the syntax, from within Oddjob Designer the value attribute is configured simply as ${jmx-monitor/"java.lang:type=Memory".HeapMemoryUsage.used}.
  2. The Check job then checks that the value of the variable is greater than 40 Meg. If the check passes then the Sequential Job will run the next job.
  3. The last job is an Invoke job that invokes the gc operation on the MBean. The source property is the target of the invocation and is a reference to the MBean, ${jmx-monitor/"java.lang:type=Memory"}.

I admit that invoking gc, suggesting Garbage Collection to the remote JVM, is fairly futile but it’s really difficult to think up both simple and meaningful examples! Hopefully though, you can see how easy it would be to monitor your own remote processes with Oddjob and JMX and execute operations on them.

For those that would like to try this at home – here’s that problematic program:

public class MemoryLeak {

	private static final List<byte[]> buffers = new ArrayList<byte[]>();

	public static void main(String... args) throws InterruptedException  {
		while (true) {
			buffers.add(new byte[1048576]);
			Thread.sleep(1000);
		}
	}
}

And here’s how it’s run – with Oddjob of course!

<oddjob id="this">
  <job>
    <exec dir="${this.dir}\.."><![CDATA[java
-Dcom.sun.management.jmxremote.port=2012
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-cp classes oddjob.demos.MemoryLeak]]></exec>
  </job>
</oddjob>

And Also

While I was refactoring the client, I also implemented a little utility that will build the standard verbose URL connection string from just the connection and port, like JConsole does. In fact I might have had a little bit of a peek at the JConsole code, but Oddjob’s is better because you can optionally specify the URL path as well so you can access an instance from an RMI server – although everyone these days just seems to go via the Platform MBean.

Now it’s definitely definitely time for that Release!

Comments are closed.