Developing a custom JMX client
In this article, we will look at how to develop a JMX client. In the first section of the article, we will look at how to develop our JMX client; and in the second part, we will look at configuring and running the client. We will be using our Notepad example that we have developed from previous articles.
Writing the JMX Client
Here are the steps that our client will need to perform in
order to connect to an MBean.
- Attach to the Java virtual machine which is running Notepad
- Load the JMX agent, if it is not already running
- Connect to the JMX agent
- Locate and manipulate the MBean
We will now look at each of these steps in greater detail.
1. Attach to Java Virtual Machine
A JMX client requires a JMXServiceURL
to connect to an MBean. The URL points to the JMX server and is typically
entered by the user or obtained from the JVM that is running the application.
We will assume that we are connecting to a local JVM so what we will do is use
the Attach
APIs to locate the desired JVM. The Attach API is part located in the com.sun.tools.attach
package. The following is a code snipped to locate the JVM running Notepad.jar
//List all the currently running JVMs |
The code is quite straightforward. We use the VirtualMachine
class to list all the JVMs that are currently running. Once we have the JVM
list, a typical application would open a dialog box to ask the user to select
the JVM. Since we know exactly which JVM we want, we loop through the JVM list
to look for our Notepad JVM. The vmd.toString() method prints the following format:
sun.tools.attach.LinuxAttachProvider@1bd747e: 25485 Notepad.jar
sun.tools.attach.LinuxAttachProvider@1bd747e: 29779
We use this fact to match the string ending with 'Notepad.jar'.
2. Load the JMX Agent
Next check if the JMX agent for that JVM has been loaded.
To do this, check if the com.sun.management.jmxremote.localConnectorAddress
property has been set on the target JVM. If it has not been set, then we know
that the JMX agent has not been loaded. We can now go ahead to load the agent.
The code snippet shows how this is done:
//CONNECTOR_ADDRESS_PROPERTY = |
One other point to note is that we need to specify which port the agent should be running on. So when we load the agent using loadAgent() method, we also need to specify the port. In our example above, the agent is loaded on port 54321.
3. Connect to the JMX Agent
Using the connectorAddress, we now create a connection to
the running MBean agent. The following code snippet shows how this is done:
JMXServiceURL url = new JMXServiceURL(connectorAddress); |
4. Locate and Manipulate the MBean
Once we have established a connection to the MBean, we can
now query and manipulate the MBean. However, before we can do that, there is
just one final hurdle; we have to specify which MBean we are interested in. An
application can expose more than one MBean. In part
2 of the JMX series, the NotepadManagement
MBean was exposed as 'Notepad:name=notepad'.
So we create a ObjectName
instance like so
ObjectName notepad = new ObjectName("Notepad:name=notepad"); |
The notepad object will now be the name reference to our MBean. Here are some operations that you can perform:
- Set and get attributes
//Query an attribute |
- Invoke operations
System.out.println(server.invoke(notepad, "toUpperCase", null, null)); |
- Receive notifications
To receive JMX notifications, you have to implement the NotificationListener
interface. The interface has only one method, handleNotification().
You will also need to register the listener with the addNotificationListener().
The addNotificationListenerObjectName
has four parameters: they are the name of the MBean (ObjectName), the listener, a NotificationFilter
for filtering unwanted notifications, and an arbitrary object to be associated
with this instance of the listener. The last 2 parameters can be set to null. Here is how
a typical registration might look like:
server.addNotificationListener(notepad, new |
Running the JMX Client
Before you run the JMX client, you have to set up a password
file. The template password file is located at <JDK_HOME>/jre/lib/management
directory. Go into that directory where you can rename or copy jmxremote.password.template
to the jmxremote.password.
Make the jmxremote.password
file readable only to the user who will be executing Notepad.jar. For example,
if user fred is going to run Notepad.jar, then make jmxremote.password readable
only to user fred. On Solaris/Linux the permission for that file will look like
this
-r-------- 1 fred users 2856 Nov 2
Now run Notepad.jar. Once Notepad is up, type "hello world" into the editor.
Run the client as follows; you can get the source here.
java -cp $JAVA_HOME/lib/tools.jar:./Notepad.jar:. Main
or on Windows
java -cp %JAVA_HOME%\lib\tools.jar;.\Notepad.jar;. Main
Why the reference to tools.jar and Notepad.jar in the classpath? This is because tools.jar contains the Attach API classes. Since the Attach APIs are not part of java or javax packages, they are not in the system's classpath. We will also need to include tools.jar into our classpath when you compile the client.
Notepad.jar is required when the MBean sends a MatchNotification object. If you recall, MatchNotification is the notification object generated by NotepadManagement MBean. The class file is part of Notepad.jar. So when the client receives the notification it needs the class file when it deserializes the event.
Beans, Beans, Beans
The JMX technology is very powerful and flexible. We
have, however, only looked at one type of MBean known as the Standard MBean. It
is the easiest to write; there are limitations like having all class files
present. The other three MBeans are Dynamic, Model and Open. See Wikipedia reference for a quick
introduction. O'Reilly has an excellent book on JMX. You can find it here.
*Actually this is not strictly true. JConsole has a set of APIs that allows you to create extensions for it. See JConsole API.
Lee Chuk-Munn has been programming in the Java language since 1996, when he first joined Sun Microsystems in Hong Kong. He currently works as a senior developer consultant and technology evangelist for Technology Outreach at Sun in Singapore. Chuk's focus is in Java APIs, Java EE, Java SE, and Java ME. Chuk graduated in 1987 from the Royal Melbourne Institute of Technology in Melbourne, Australia, where his favorite subject was compiler theory.