Improving the Fidelity of the JFR Method Profiler

One nice property of the JFR method profiler is that it does not require for the threads to be at safe points for stacks to be sampled. However, since the common case is that stacks will only be walked at safe points, HotSpot normally does not provide metadata for non-safe point parts of the code, which means that such samples will not be properly resolved to the correct line number and BCI. That is, unless you specify:

-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints

With the DebugNonSafepoints, the compiler will generate the necessary metadata for the parts of the code not at safe points as well.

Big thanks to Doug Simon and Gilles Duboscq for noting this!

My Sessions at JavaOne 2014

So despite my recent blog of despair, I am now involved in two sessions at JavaOne 2014. Another Oracle session had to be cancelled, which allowed some room for a session on how to use the Java Flight Recorder. There will likely be a guest appearance from another Oracle team on that session too. :)

So here are the sessions I am involved in:


Using Oracle Java Flight Recorder [CON10912]

The former Oracle JRockit Mission Control, a feature of Oracle Java SE Advanced, is now called Oracle Java Mission Control. This tools suite includes tools for monitoring, managing, and profiling your Java application without introducing the performance overhead normally associated with tools of this type. One of the most important components of Oracle Java Mission Control is Oracle Java Flight Recorder. This session discusses how to use Oracle Java Flight Recorder to analyze various aspects of Java programs running on Oracle’s HotSpot JDK.

The presentation
• Explains how Oracle Java Flight Recorder works
• Shows different ways to control Oracle Java Flight Recorder
• Shows examples of how to analyze recordings in different ways

Tuesday, Sep 30, 5:30 PM – 6:15 PM - Hilton – Continental Ballroom 4

and:

Be in Control of Your JavaFX Mission [CON2262]

Starting with JDK 8u20, Java Flight Recorder (JFR) and Java Mission Control (JMC) can help you look under the hood of the JavaFX runtime to better understand the behavior of your application. This session takes you on a tour of all the steps from launching your app to visualizing collected data in the JavaFX plug-in of JMC. It provides a brief overview of the JavaFX architecture required to correctly interpret and analyze presented data. JavaFX developers will learn how interaction with JFR is implemented in the JavaFX runtime and how it can be extended to collect and visualize information they need. 

Thursday, Oct 2, 11:30 AM – 12:30 PM - Hilton – Plaza B

Looking forward to seeing you there! :)

JavaOne 2014 and The Mistake of the Year

Soooo, this was a pretty hectic year. What with the relocation to Switzerland and all. Internally within Oracle I submitted two talks of my own for consideration to JavaOne 2014, plus one together with Oleg Mazurov. They were all internally accepted within Oracle to be submitted to the JavaOne 2014 conference call for papers. Guess who forgot to actually submit the talks? Yep.

That said, all is not lost. Oleg did not forget to submit the one I will be co-presenting with him.

This is the talk:


Be in Control of Your JavaFX Mission [CON2262]

Starting with JDK 8u20, Java Flight Recorder (JFR) and Java Mission Control (JMC) can help you look under the hood of the JavaFX runtime to better understand the behavior of your application. This session takes you on a tour of all the steps from launching your app to visualizing collected data in the JavaFX plug-in of JMC. It provides a brief overview of the JavaFX architecture required to correctly interpret and analyze presented data. JavaFX developers will learn how interaction with JFR is implemented in the JavaFX runtime and how it can be extended to collect and visualize information they need. 

Thursday, Oct 2, 11:30 AM – 12:30 PM - Hilton – Plaza B

If anyone wants to meet up, I will be in SF on Thursday. Also, since I screwed up, I will make amends by:

  • Publishing a JMC tutorial on the Mission Control home page.
  • Publishing it by the end of JavaOne.
  • Making it more comprehensive than the HoL I was planning for JavaOne.

I’ll say something on my twitter when the tutorial is available.

Hope to see you at JavaOne! :)

Java Mission Control 5.4.0 Released!

Yay! Today a new version of Java Mission Control was released together with 8u20! This blog entry will provide a quick summary of some of the new features and fixes in JMC 5.4.0. Since I didn’t write anything when the 5.3.0 was released, I will cover a few features that were already included in 5.3.0. Both the 5.3.0 and 5.4.0 are minor, incremental releases, so there are no radical changes. Those will happen in JMC 6.0, which is where most of the development effort has been taking place for a while now. ;)

New Plug-ins!

Two new plug-ins were introduced with JMC 5.4.0: the Java FX plug-in and the Eclipse IDE launcher plug-in. The Java FX plug-in can be installed in both the stand alone and Eclipse plug-in version of JMC, whilst the launcher plug-in is only available for the Eclipse plug-in version of JMC.

The Java FX plug-in

In 8u20 Java FX integrates with the Java Flight Recorder, producing events about Java FX pulses and input events. With JMC 5.4.0 there is an experimental plug-in that can be downloaded into JMC which provides custom visualization for these events.

javafx 

Using the plug-in, you can quickly look at the pulses and see how much time was spend in the different phases.

javafx_input

And for completeness, above is a picture of the view for the input events. If you’d like, you can use the built in GUI editor to spice it up further:
javafx_input_spiff

The Launcher Integration plug-in

The launcher integration plug-in makes it easier to run your applications from within Eclipse with the Java Flight Recorder enabled. A new alternative is added to the “Run As” menu when the plug-in is installed – Java Application with Flight Recorder.

runwithjmc

A new launcher alternative will be available, “Java Application With Flight Recorder”, which adds an extra tab in the Eclipse Run Configuration dialog to help you launch your Java application with a flight recording running.

launchconfig

At the bottom of the Flight Recorder launcher tab you will see the JFR related arguments that will be added to the VM arguments to make it all happen.

Miscellaneous Enhancements

Aside from the two plug-ins, there are quite a few enhancement to the base JMC product. I’ve selected a few user facing ones. (The pictures can be clicked for higher resolution versions.)

  • You can now select how to aggregate method frames in stack traces, either by method (default), line number or by byte code index (or any combination). When you choose line number, you will now see the line numbers in the stack trace view. For BCI the recording must have been created with 8u20 or later.
    frames_by_line_number
  • The dump JFR trigger action no longer requires a default recording to operate upon. Any ongoing recording will do.
  • Using ctrl+mouse wheel in the thread graph in the Flight Recorder UI to zoom, will now zoom towards the mouse pointer.
    zooming
  • JMC will now choose the stronger AES/SHA-2 cipher over triple DES/SHA-1, if available, for PBE.
    cipher
  • In 5.3.0 a new content type system was introduced. It is currently only used in the JMX console, but will be used all over Mission Control in 6.0.0 and later. The content type system associates a value with its physical quantity and unit of measurement, making it possible for JMC to render the value better and for the user to input values in a much more convenient way. For example, in the Memory Pool MBeans it is possible to set a usage threshold. Previously a (usually) very long number stating the number of bytes would have to be entered. Now that value can be entered with whatever unit you please.
    content_type 
    Attributes that have no physical quantity and unit specified can have one set by the user. custom_units
    The best would of course be if there was a standardized way of adding this metadata to the MBean attributes themselves, instead of (only) to the JMC JMX console. We hope to include such metadata in the JMX spec in the future.
  • Also in 5.3.0, the console tab groups and tabs were redistributed and normalized, so that no tab groups would need to be visible by default.
    console 
    Installing plug-ins may make the tab groups area re-appear.
  • In 5.3.0 there was a new context action introduced for copying stack traces to the clipboard (JFR).
  • There was also a new user interface introduced showing the VM flags (JFR).
    vmflags
  • Attributes with the same update interval and on the same MBean are now fetched at the same time to minimize roundtrips.
  • In the memory tab, there is now the possibility to take heap histograms. Note that you need to be connected to a JDK 8 JVM for this to show up.
    heap_histogram
    Click the Update Heap Histogram button to take a new snapshot. The difference between the two last ones will be calculated and shown in the Delta column.

Bugfixes

We’ve also fixed a bunch of bugs! I’ve selected a few:

  • The dropins folder now works as expected. To install a plug-in, it can simply be dropped into the JDK_HOME/lib/missioncontrol/dropins folder.
  • Installing experimental plug-ins in a shared installation now works. Previously installing plug-ins in a shared installation could fail silently.
  • JMC and JFR did not agree on how to specify some time units, making it impossible to use recording templates containing time values specified in minutes interchangeably as server side and client side templates. Fixed.
  • JMC no longer hangs when starting up on Mac (due to an SWT/Swing interop problem on Mac OS X – we have a workaround).

Summary

  • There is a new version of Java Mission Control available now – JMC 5.4.0.
  • It is shipped with Oracle JDK 8u20.
  • It is also available as a set of Eclipse plug-ins.
  • Even though most of the development effort is put into the next major version of JMC, there are lots of useful new features and bug fixes in these incremental releases.

 

Further reading and useful links

Related Blogs:
Creating Flight Recordings
Low Overhead Method Profiling with Mission Control

The Mission Control home page:
http://oracle.com/missioncontrol

Mission Control Base update site for Eclipse:
http://download.oracle.com/technology/products/missioncontrol/updatesites/base/5.4.0/eclipse/

Mission Control Experimental update site (Mission Control plug-ins):
http://download.oracle.com/technology/products/missioncontrol/updatesites/experimental/5.4.0/eclipse/

The Mission Control Facebook Community Page (not kidding):
http://www.facebook.com/pages/Java-Mission-Control/275169442493206

Mission Control on Twitter:
@javamissionctrl

Me on Twitter:
@hirt

Moving to Switzerland – hirt.se will be down!

Hi friends!

Sorry for the radio silence lately. I’ve been spending a lot of time preparing for my family’s relocation to Switzerland. Since I will be bringing my computers, and since traveling from Sweden to Switzerland is far from instantaneous, this means that hirt.se will be down for a couple of days. Minimum. Murphy’s law says it could be weeks.

The server is unplugged the 21st of June. With lots of luck it will be up again by the 23rd. Sorry about the upcoming interruption.

Have a great summer and happy coding! :)

/M

Executing Diagnostic Commands Using Attach

Sometime it can be very useful to have programmatic access to the Diagnostic Commands available in the Oracle JRE. This is of course both highly dependent on the Oracle JDK and very unsupported, so, as usual, please use responsibly.

Here comes the usual disclaimer:

The following blog entry will describe UNSUPPORTED functionality. This means that relying on the described APIs or functionality may BREAK your code/plugin with any given update of the JDK and/or Mission Control.

The Attach API

There is an API that allows a Java process to attach to another Java process. This is the API used by several different Java tools to both enumerate the locally running Java processes, as well as do things like start up the management agent. The API is usually just called the Attach API, and one of the entry points is the com.sun.tools.attach.VirtualMachine class.

You can use the VirtualMachine class to enumerate all the locally running Java processes (with the same effective user as the process doing the listing) on the machine like this:

List<VirtualMachineDescriptor> vmList = VirtualMachine.list();
for (VirtualMachineDescriptor descriptor : vmList) {
    System.out.println(String.format(“%s %s”, descriptor.id(), descriptor.displayName()));
}

This is how you attach to a running Java process:

VirtualMachine.attach(<PID>); 

<PID> is the process ID as a String. The reason it is a String is probably to not assume that all Operating Systems use integer values for their process identifiers. I guess having the identifier as a String could also come in handy when addressing Isolates/MVM and other more complicated scenarios where what constitutes the “Java Process” becomes a bit more blurry. Anyways, once you have your VirtualMachine there is all kinds of fun you can do, like loading Java agents and agent libraries etc. The most important thing, however, is to detach. Never forget to detach, or you will start leaking process handles.

Invoking Diagnostic Commands

To invoke diagnostic commands, we will need to cast our VirtualMachine to a HotSpotVirtualMachine. Here is how to execute the Thread.print DiagnosticCommand:

VirtualMachine vm = VirtualMachine.attach(<PID>);
HotSpotVirtualMachine hsvm = (HotSpotVirtualMachine) vm;
hsvm.executeJCmd(“Thread.print”);

Or, here as a compilable example:

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import sun.tools.attach.HotSpotVirtualMachine;

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;

public class DiagnosticCommandExample {

    public static void main(String[] args) throws AttachNotSupportedException,
            IOException {
        if (args.length == 0) {
            System.out.println(“Usage: InvokeDiagnosticCommand <PID>”);
            System.exit(2);
        }
        VirtualMachine vm = VirtualMachine.attach(args[0]);
        if (!(vm instanceof HotSpotVirtualMachine)) {
            System.out.println(“Only works on HotSpot!”);
            System.exit(3);
        }
        HotSpotVirtualMachine hsvm = (HotSpotVirtualMachine) vm;
        System.out.println(readInputStreamAsString(hsvm.executeJCmd(“Thread.print”)));
    }

    public static String readInputStreamAsString(InputStream in)
            throws IOException {
        BufferedInputStream bis = new BufferedInputStream(in);
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        int result = bis.read();
        while (result != -1) {
            byte b = (byte) result;
            buf.write(b);
            result = bis.read();
        }
        return buf.toString();
    }
}

Summary

Using the attach API is not supported and the APIs may change at any time. That said, it can still be quite useful for putting together small utilities.

Clarification: Alan Bateman pointed out to me that whilst linking to the sun.tools.attach.HotSpotVirtualMachine class is indeed unsupported, the Attach API in itself is supported and documented.

Building a Custom JMC JMX Console Plug-in

Last week I ran into Gerrit Grünwald (@hansolo_) whilst demoing JMC in the Oracle booth at JFokus. I’d built a little RPi sensor board to have in my summer house, and since there is a lot of interest in the Internet of Things, I thought I’d contribute by showing how easy it is to hook up the JMX Console to one of those things.

sensor_board  temp

We also had a very neat demo sporting a plug-in for the JMC console for controlling our resident LEGO robot (caught in an intimate moment with another robot in the picture below).

robot_love mindstorms_demo_ui

Anyways, Gerrit wanted to know how to extend the JMC JMX Console with custom JavaFX visualization. Since the Java FX part will be much easier once JDK 8 and JMC 5.3.0 is out, I’ll leave that for a (not too distant) future blog post. Here is the first step though – how to build your own JMC console plug-in!

Preparations

The easiest way to get going is by installing the JMC PDE plug-in into Eclipse.

    1. Get an Eclipse classic
      For JMC 5.2, get Eclipse 3.8.2 up to 4.2.x (Juno)
      For JMC 5.3 (out soon), get Eclipse 3.8.2 and any 4.x (Kepler will work fine)
    2. Install JMC from the update site
      The update site link can be found here: http://www.oracle.com/missioncontrol
      Follow the installation instructions.
      Note: Later releases of Eclipse are pickier about certificate validation – if you run into problems because download.oracle.com maps to akamai hosts, try using http instead of https in the update site URL.
    3. Next install the PDE plug-in from the experimental update site
      The URL for the experimental update site can be found on the Mission Control page too: http://www.oracle.com/missioncontrol
      The plug-in to install is the Development/Java Mission Control PDE Integration one.

Next you need to set the target platform to your JMC installation.

    1. Go to Preferences
    2. Type targ in the filter box and select the “Target Platform” node in the preferences tree
    3. Click Add, to open the wizard for adding a new target platform
    4. Click next, since you want to start with an empty target definition
    5. Name the target JMC and click Add
    6. Select Installation and hit Next
    7. Select your JAVA_HOME/lib/missioncontrol folder
    8. Hit Finish

You are now set to start developing your first Mission Control plug-in.

JMC JMX Plug-in Hello World

First we need to create a new plug-in project. Select File | New | Other. Select Plug-in Project and hit next. Name your project and hit next. Name your plug-in and hit next. Now you should be able to select a custom wizard for creating a JMC console plug-in:

templates

Select Simple Mission Control Console Tab Wizard and hit Next. Change the class name and tab name to your liking and finish the wizard. You should now have a new project. With the current 5.2.0 PDE plug-in, you may have a weird compilation error due to an unnecessary import as well. If you do, simply right click on the offending class and choose organize imports to get rid of the import (remember to save the class after fixing the problem):

organize_imports
You can now run Mission Control with your new plug-in by selecting the project and choosing Run As | Eclipse Application from the context menu. If you connect with the management console, you should see something like this:

HelloJMC

Building the Plug-in

This is how you build your plug-in:

    1. Select the plug-in project and choose Export… from the context menu
    2. In the following wizard, select Deployable plug-ins and fragments
    3. Select a Directory for where to put the plug-in and hit Finish.

That’s it. You should now have a plug-in jar file.

Installing the Plug-in

How easy it is to install your plug-in depends on the version of JMC you are using.

For 5.3.0 you simply copy the plug-in into the JMC_HOME (i.e. JDK_HOME/lib/missioncontrol) dropins folder. Done!

For 5.2.0 this is quite a lot more elaborate. You first need to generate some p2 metadata. This can be done using Eclipse like this:

eclipse -application org.eclipse.equinox.p2.publisher.FeaturesAndBundlesPublisher -metadataRepository <metadatadir> -artifactRepository <metadatadir> -bundles <pluginsfolder> -compress –publishArtifacts

Where <metadatadir> is where you want the metadata published, and <pluginsfolder> is the plug-ins folder where you exported your plug-in.

For example:

macbookpro:~marcus$ /Users/marcus/Applications/eclipse_4.2.2/Eclipse.app/Contents/MacOS/eclipse -consoleLog -application org.eclipse.equinox.p2.publisher.FeaturesAndBundlesPublisher -metadataRepository file:/Users/marcus/Builds/repo -artifactRepository file:/Users/marcus/Builds/repo -bundles /Users/marcus/Builds/plugins -compress -publishArtifacts

The result in <metadatadir> should be two jars and a plugins folder with your plug-in in it.

Next you need to tell p2 to install the plug-in. JMC includes the p2 director, so installing can be done like this (using sudo for administrative rights – on windows you might want to open a shell with admin rights):

sudo jmc -nosplash -application org.eclipse.equinox.p2.director –repository <metadatadir> –installIU <pluginname>/<full version> -destination <jmchome> -profile JMC

For example:

macbookpro:~marcus$ sudo /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/lib/missioncontrol/Java\ Mission\ Control.app/Contents/MacOS/jmc -nosplash -application org.eclipse.equinox.p2.director -repository file:/Users/marcus/Builds/repo -installIU se.hirt.blogs.jmxconsole/1.0.0.201402132124 -destination /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/lib/missioncontrol/ -profile JMC

Uninstalling

If you wish to uninstall the plug-in, you just remove it from the dropins folder in 5.3.0. For 5.2.0 you use the uninstallIU command:

sudo jmc -nosplash -application org.eclipse.equinox.p2.director –uninstallIU <pluginname>/<full version> -destination <jmchome> -profile JMC

For example:

macbookpro:~marcus$ sudo /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/lib/missioncontrol/Java\ Mission\ Control.app/Contents/MacOS/jmc -nosplash -application org.eclipse.equinox.p2.director -uninstallIU se.hirt.blogs.jmxconsole/1.0.0.201402132124 -destination /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home/lib/missioncontrol/ -profile JMC

Summary

This blog entry described how to create a custom plug-in for the Java Mission Control JMX Console, and how to install the newly created plug-in. The installation process of custom plug-ins is simpler in the upcoming 5.3.0 version of Mission Control.

Using the JVM Performance Counters

So, in JRockit there was this neat little dynamic MBean from which you could access all the JVM performance counters as attributes. Tonight I ended up in an e-mail thread leading me to think about how to retrieve the HotSpot ones. This is of course all very unsupported, and counter names/content and even the very API is subject to change at any given release. I am providing this information mostly as a reminder to myself. Who knows, someone might find this useful.

I will now go ahead and show how something similar to the PerformanceCounters MBean available in JRockit can be built. I recommend against doing this in any kind of production scenario, as the PerformanceCounter API is totally unsupported. Please don’t ask me what a certain counter means – you probably shouldn’t be using these in the first place. This is all for lolz. :)

Here comes the usual disclaimer:

The following blog entry will describe UNSUPPORTED functionality. This means that relying on the described APIs or functionality may BREAK your code/plugin with any given update of the JDK and/or Mission Control.

Performance Counter Hello World

If you ever used JRockit, you may fondly remember the old jrcmd utility, which now exists in a HotSpot incarnation as jcmd. Well, jrcmd had an option, –l, which would list all the the performance counters in the target JVM. The following code will let you implement something similar to the jrcmd –l command. Note that the PerformanceCounter API resides in a package most IDEs will restrict access to. You will need to change your project settings accordingly for the following to compile.

Anyways, here is a hack to list all the performance counters for a particular PID:

import java.io.IOException;
import java.nio.ByteBuffer;

import sun.management.counter.Counter;
import sun.management.counter.perf.PerfInstrumentation;
import sun.misc.Perf;

public class PerfCounterTest {

    public static void main(String[] args) throws IOException {
        if (args.length != 1) {
            System.out.println(“Usage: PerfCounterTest <PID>”);
            System.exit(2);
        }
        Perf p = Perf.getPerf();
        ByteBuffer buffer = p.attach(Integer.parseInt(args[0]), “r”);
        PerfInstrumentation perfInstrumentation = new PerfInstrumentation(buffer);
        for (Counter counter : perfInstrumentation.getAllCounters()) {
            System.out.println(String.format(
                    “%s = %s [Variability: %s, Units: %s]“, counter.getName(),
                    String.valueOf(counter.getValue()),
                    counter.getVariability(), counter.getUnits()));
        }

    }
}

Note that you will need the “sun.misc.Perf.getPerf” permission to be able to access the Perf instance when running with a security manager.

From here to a fully functional Dynamic MBean, the step is pretty short.

PerformanceCounterMBean á la JRockit for HotSpot

Here is an example of how code exposing the Performance Counters as a Dynamic MBean can look like:

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.RuntimeOperationsException;

import sun.misc.Perf;
import sun.management.counter.Counter;
import sun.management.counter.perf.PerfInstrumentation;

public class PerfCounters implements DynamicMBean {
    public final static ObjectName MBEAN_OBJECT_NAME;
    public final Map<String, Counter> counterMap;
    private final MBeanInfo info;

    static {
        MBEAN_OBJECT_NAME = createObjectName(“se.hirt.management:type=PerfCounters”);
    }

    public PerfCounters() {
        counterMap = setUpCounters();
        info = createMBeanInfo();
    }

    @Override
    public Object getAttribute(String attribute)
            throws AttributeNotFoundException, MBeanException,
            ReflectionException {
        if (attribute == null) {
            throw new RuntimeOperationsException(new IllegalArgumentException(
                    “The attribute name cannot be null.”),
                    “Cannot invoke getAttribute on ” + MBEAN_OBJECT_NAME
                            + ” with null as attribute name.”);
        }
        Counter c = counterMap.get(attribute);
        if (c == null) {
            throw new AttributeNotFoundException(
                    “Could not find the attribute ” + attribute);
        }
        return c.getValue();
    }

    @Override
    public void setAttribute(Attribute attribute)
            throws AttributeNotFoundException, InvalidAttributeValueException,
            MBeanException, ReflectionException {
        if (attribute == null) {
            throw new RuntimeOperationsException(new IllegalArgumentException(
                    “The attribute name cannot be null.”),
                    “Cannot invoke setAttribute on ” + MBEAN_OBJECT_NAME
                            + ” with null as attribute name.”);
        }
        Counter c = counterMap.get(attribute);
        if (c == null) {
            throw new AttributeNotFoundException(
                    “Could not find the attribute ” + attribute + “.”);
        }
        throw new RuntimeOperationsException(
                new UnsupportedOperationException(),
                “All attributes on the PerfCounters MBean are read only.”);
    }

    @Override
    public AttributeList getAttributes(String[] attributes) {
        AttributeList attributeList = new AttributeList();
        for (String attribute : attributes) {
            try {
                attributeList.add(new Attribute(attribute,
                        getAttribute(attribute)));
            } catch (AttributeNotFoundException | MBeanException
                    | ReflectionException e) {
                // Seems this one is not supposed to throw exceptions. Try to
                // get as many as possible.
            }
        }
        return attributeList;
    }

    @Override
    public AttributeList setAttributes(AttributeList attributes) {
        // Seems this one is not supposed to throw exceptions.
        // Just ignore.
        return null;
    }

    @Override
    public Object invoke(String actionName, Object[] params, String[] signature)
            throws MBeanException, ReflectionException {
        throw new MBeanException(new UnsupportedOperationException(
                MBEAN_OBJECT_NAME + ” does not have any operations.”));
    }

    @Override
    public MBeanInfo getMBeanInfo() {
        return info;
    }

    private static ObjectName createObjectName(String name) {
        try {
            return new ObjectName(name);
        } catch (MalformedObjectNameException e) {
            // This will not happen – known to be wellformed.
            e.printStackTrace();
        }
        return null;
    }

    private Map<String, Counter> setUpCounters() {
        Map<String, Counter> counters = new HashMap<>();
        Perf p = Perf.getPerf();
        try {
            ByteBuffer buffer = p.attach(0, “r”);
            PerfInstrumentation perfInstrumentation = new PerfInstrumentation(
                    buffer);
            for (Counter counter : perfInstrumentation.getAllCounters()) {
                counters.put(counter.getName(), counter);
            }
        } catch (IllegalArgumentException | IOException e) {
            System.err.println(“Failed to access performance counters. No counters will be available!”);
            e.printStackTrace();
        }
        return counters;
    }

    private MBeanInfo createMBeanInfo() {
        Collection<Counter> counters = counterMap.values();
        List<MBeanAttributeInfo> attributes = new ArrayList<>(counters.size());
        for (Counter c : counters) {
            if (!c.isVector()) {
                String typeName = “java.lang.String”;
                synchronized (c) {
                    Object value = c.getValue();
                    if (value != null) {
                        typeName = value.getClass().getName();
                    }
                }
                attributes.add(new MBeanAttributeInfo(c.getName(), typeName,
                        String.format(“%s [%s,%s]“, c.getName(), c.getUnits(),
                                c.getVariability()), true, false, false));
            }
        }
        MBeanAttributeInfo[] attributesArray = attributes.toArray(new MBeanAttributeInfo[attributes.size()]);
        return new MBeanInfo(
                this.getClass().getName(),
                “An MBean exposing the available JVM Performance Counters as attributes.”,
                attributesArray, null, null, null);
    }
}

And here is a little test application that registers the MBean with the platform MBean server and then waits around, giving you an opportunity to hook up with Mission Control and try it out:

import java.io.IOException;
import java.lang.management.ManagementFactory;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.NotCompliantMBeanException;

public class PerfCounterMBeanRunner {

    public static void main(String[] args) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, IOException {
        ManagementFactory.getPlatformMBeanServer().registerMBean(new PerfCounters(), PerfCounters.MBEAN_OBJECT_NAME);
        System.out.println(“Press enter to quit!”);
        System.in.read();
    }

}

If you use the JMX Console to connect to a JVM where the PerfCounters MBean is registered, you should be able to find the PerfCounters MBean using the MBean Browser. There should be quite a few performance counters available:

JMC_perf_counters

Conclusion

Sample code for using the proprietary JVM performance counter API was provided, as well as example code on how to implement a version of the old jrcmd –l command, as well as the old PerformanceCounter MBean of JRockit. Again, these examples are using proprietary APIs that may break at any given release. Use responsibly!

jrockit_duke_love

Stronger Crypto for Your Passwords in JMC

If you would like to use a stronger PBE cipher than triple DES & SHA-1 for storing passwords in JMC, this is how to go about it:

    1. Download a crypto provider containing the cipher you want. For example the latest provider jar from Bouncy Castle (at the time of writing, this was bcprov-jdk15on-150.jar)
    2. Copy the jar to JAVA_HOME/jre/lib/ext
    3. Edit your JAVA_HOME/jre/lib/security/java.security file to include the Bouncy Castle provider. Look for the security.provider entries and add a new entry:

      security.provider.N=org.bouncycastle.jce.provider.BouncyCastleProvider
      , where N is the number of the last entry plus one, for example:

      security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider

    4. For access to the strongest ciphers, download the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for your JDK version (this one for example), and unpack the two jar files into JAVA_HOME/jre/lib/security/.

Finally you need to select which cipher to use in the preferences (Window | Preferences, click Java Mission Control). Before adding bouncy castle, you should have had something like this:

security_prefs

After adding Bouncy you should see something like this:

bouncy

Good luck!

Accessing 1-wire Protocol Devices from Java

More Raspberry Pi fun with Java! For an Adafruit LCD Shield library, check out my previous blog.

So, instead of just playing around for fun, I decided to actually do something useful. In this case I wanted a little remote sensor station, which I can plug-in wherever I want to, and communicate with over http over GSM.

Building It

First of all you need to bunker up on as many DS18B20s and as many AM2302/DHT11/DHT22’s you think you’ll need. There are plenty of articles out there on how to configure them. I decided to do it a tiny bit differently to most examples by hooking up the power pin to the 5V rail (both since the specs indicate that you can run longer cable lengths if you do so and since more current can be sourced from the 5V rail). The data is pulled up to the 3.3V rail, just like in all the examples. Note that a bunch of DS18B20s can be hooked up in parallel and communicated with over a single GPIO port. Also note that this is NOT possible with the DHT sensors, which will need one GPIO port per sensor.

Ultimately I decided to have two (optional) DS18B20s and one AM2302 on my board, and I used an Adafruit Perma Proto to hook it all up. Mostly because they are pretty. ;) To connect the AM2302, I used a Molex jumper assembly, and for the DS18B20s I decided to use RJ-11s. I can highly recommend the RJ-11s! The connectors take a bit of space on the card, and they do require you to mutilate the poor Perma Proto a bit (drill larger holes), but attaching/removing sensors is a joy. Here is a picture of the thingy with all the sensors connected:

sensor_board

In my build I will also use an LCD shield for local control and readouts without necessarily having access to a monitor. I also added a few buttons and LEDs, mostly to satisfy my youngest son.

I guess those could come in handy for diagnostics later. :)

Now, the 1-wire protocol used by the DS18B20 (Dallas 1-wire) and the 1-wire protocol used by the DHT sensors (AM2302, DHT11, DHT22) are quite different. Both of these require a bit of time sensitive bit-banging. Fortunately, that work has already been done for us.

For the DS18B20 there are two modules available which will expose all the DS18B20s as files under /sys/bus/w1/devices. Simply add w1-gpio and w1-therm to /etc/modules. Note that you must have the DS18B20s on GPIO port 4 for the module to work.

For the DHT sensors there is no module, but Adafruit has a driver binary that can be downloaded as described here. The Adafruit_DHT must be somewhere on the path for the Java library to work, for example /usr/bin.

Java Access

Once you have added the modules and put the Adafruit_DHT binary on the path, there is only a tiny bit of configuration left to do. The library should automatically discover all DS18B20s you have. If you only happen to have one AM2302 on GPIO-pin 22, you are good to go. If not, you need to edit the property file dhtsensors.properties in the w1.jar to correspond to your setup:

# Specify devices to use with the Adafruit_DHT driver in this file.
# If you have no such devices, just comment everything out.
#
# Type can be one of the following:
# 2302 (for AM2302)
# 11 (for DHT-11)
# 22 (for DHT-22)
sensor0.pin=22
sensor0.type=2302

If you have no DHT sensors, simply comment out the lines. If you have more than one, simply add two more lines for every sensor, indicating which type and what pin they are on. For example:

sensor0.pin=22
sensor0.type=2302
sensor1.pin=23
sensor1.type=2302
sensor2.pin=24
sensor2.type=22

To test that everything is set up properly, simply run:

sudo java –jar w1.jar

Note that Pi4J isn’t needed on the classpath. We’re relying on the DHT driver and the w1-gpio mod to provide the necessary interface. We’re basically just reading and parsing strings provided by others doing the actual bitbanging.

The output should look something along the lines of this:

Found 4 sensors!

Temperature(28-000004f7960a):23,38°C
Temperature(28-000004f78caf):23,56°C
Temperature(2302@22-temperature):23,00°C
Humidity(2302@22-hygrometer):36,50%

Temperature(28-000004f7960a):23,38°C
Temperature(28-000004f78caf):23,56°C
Temperature(2302@22-temperature):23,00°C
Humidity(2302@22-hygrometer):36,50%

Temperature(28-000004f7960a):23,44°C
Temperature(28-000004f78caf):23,56°C
Temperature(2302@22-temperature):23,10°C
Humidity(2302@22-hygrometer):36,50%

Library Usage

The code is very simple. To get all the sensors, do:

Set<Sensor> sensors = Sensors.getSensors();

To print the sensors like in the example, do:

System.out.println(String.format(“Found %d sensors!”, sensors.size()));
while (true) {
    for (Sensor sensor : sensors) {
        System.out.println(String.format(“%s(%s):%3.2f%s”, sensor.getPhysicalQuantity(),
                                     sensor.getID(), sensor.getValue(), sensor.getUnitString()));
        Thread.sleep(1000);
    }
    System.out.println(“”);
    System.out.flush();
}       

That’s really all there is to it.

Conclusion

A simple Java library to read a few different kinds of temperature and hygrometer sensors was introduced.

Downloads: