Reading JMX Metrics

I found this question on Stack Overflow about how to connect to a locally running process and read JMX metrics. I thought I’d explain a little bit more in detail here on the blog. The steps involved are:

    1. Try to get the JMX Service URL for the local JMX agent.
    2. If you couldn’t, try to start the local JMX agent.
    3. Open an MBeanServerConnection to the local JMX agent.
    4. Do whatever MBean-ish stuff you were planning on doing, for example reading attributes.

This is pretty much as simple as it sounds. Let’s do them in order.

Getting the Service URL

When the local management agent is started, it publishes the service URL (which also contains the serialized stub for communication – take a look at the URL, it’s really quite funny) in a well known location. This can be retrieved by using the sun.management.ConnectorAddressLink class like this:

private static JMXServiceURL getLocalStubServiceURLFromPID(int pid)
        throws IOException {
    String address = ConnectorAddressLink.importFrom(pid);
    if (address != null) {
        return new JMXServiceURL(address);
    }
    return null;
}

If you didn’t get any service url, then the local management agent was not started.

Starting the Local Management Agent

Starting the local management agent can be done in various ways. In late versions of the JDK this is quite easily done. I am only going to show you the simple way today. In older you might need to resort to the attach command to load java agents (VirtualMachine vm = VirtualMachine.attach(pid).loadAgent(<path to management-agent.jar>,”com.sun.management.jmxremote”)).

To start the local agent, we simply execute the diagnostic command for starting it:

executeCommandForPID(vm, pid, “ManagementAgent.start_local”);

private static void executeCommandForPID(VirtualMachine vm, String pid,
        String cmd) throws IOException {
    HotSpotVirtualMachine hsvm = (HotSpotVirtualMachine) vm;
    hsvm.executeJCmd(cmd);
}

 

Opening the MBeanServer Connection

This, as well as doing the MBeany things you want to do once you have the connection, is done just as you would normally do it:

JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection connection = jmxc.getMBeanServerConnection();

Getting attributes:

connection.getAttribute(“java.lang:type=Memory”, “HeapMemoryUsage”);

 

Summary

    • Hooking up to the local management agent is quite easy.
    • There are valuable metrics that can be collected.
    • Here is a full example getting the JVM CPU load as well as used heap.

Controlling the Adafruit PWM Driver from Java

This article will show how to control the Adafruit 16CH 12 bit PWM driver from a Raspberry PI using Java.

  1. First step is to configure your Raspberry PI for I2C.
  2. Next step is to set up PI4J.
  3. Next is to download the tiny little library for accessing the PWM driver I just made (and/or the source).

IMG_2385

This is the raspberry hooked up to various things, one of them being the PWM driver. The easiest way to test the library is to hook up a servo to channel 0 and run the jar. The test program also accepts a servo on channel 1, and motors (via H-bridges) on channel 2 and 3. Do not, under any circumstance, run the test program with servos on channel 2 and 3, unless you edit it first.

Here is how to run the test program:

sudo java -classpath .:classes:/opt/pi4j/lib/*:./pwm.jar se.hirt.pi.adafruit.pwm.test.PWMTest

You should see something like this:

And this is how to use it:

First construct a PWMDevice:

PWMDevice device = new PWMDevice();

If you’re using the default address (0x40) on I2C bus 1, you can safely use the default constructor. Next select the PWM frequency to use. 50 Hz is, for example, good for RC servo control:

device.setPWMFreqency(50);

Next select the channel for which you want to alter the PWM signal, for example channel 0:

PWMChannel servo0 = device.getChannel(0);

Setting the PWM signal is done with the setPWM(int on, int off) channel method. We have 12 bit fidelity with which to choose when to go from low to high, and vice versa. That gives us a valid number from 0 to 4095, with 0 meaning in the beginning of the pulse, and 4095 meaning the end. So, for most servos, the internetz say that a 1ms pulse means minimum servo travel, and a 2ms pulse means maximum servo travel. 1.5 ms is centered. 50Hz means every pulse is about 20ms. 1/20 of 4096 means that minimum servo travel should be about 205. Max travel should be around 410. Of course, your mileage may vary, and servos can usually travel a bit further than this. Anyways, this would be setting min:

servo0.setPWM(0, 205);

See the test program in the source jar for more examples. Have fun!

Conclusion and Tips

  • The Adafruit 16CH 12 bit PWM driver is a wonderful little breakout board for controlling servos and motors (via an H-bridge).
  • You can use 6V for driving the servos (V+) – just make sure that the servos can handle it.
  • Servos that are specified to handle 6V are usually faster/stronger when running on 6V.
  • I am using a Polulu voltage regulator for driving the Raspberry PI off of a 3S LiPo-battery. I am using a separate BEC for servos/motors.