Adding Java Management Extensions (JMX) Instrumentation to a Java Application

This tutorial needs a review. You can edit it in GitHub following these contribution guidelines.

Expected duration: 60 minutes

The NetBeans JMX Wizard Module integrates JMX technology right into your workflow in the NetBeans IDE. This module allows you to quickly develop management applications, add management to existing applications, develop manager applications, and monitor the state of the Virtual Machine.

This tutorial shows you how to add management to an existing application (the NetBeans sample Anagrams Game application). You will first create a non-manageable Anagram Java Project. You will then use JMX Wizards to generate 90% of the management. Then you will implement the management behavior specific to the application. You will finally use the Run/Debug project with JConsole to visualize the Anagram MBeans.

Tutorial exercises

netbeans stamp 80 74 73
Figure 1. Content on this page applies to the NetBeans IDE 7.2, 7.3, 7.4 and 8.0

Prerequisites

This tutorial assumes you have some basic knowledge of, or programming experience with, the following technologies.

You will also benefit from having some knowledge on + Monitoring and Management for the Java Platform+

Software Needed for the Tutorial

For this tutorial you need to have the following software installed on your computer:

Software or Resource Version Required

NetBeans IDE

7.2, 7.3, 7.4, 8.0, Java version

Java Development Kit (JDK)

version 7 or 8

JMX plugin

Available from NetBeans Update Center

JConsole plugin

Available from NetBeans Update Center

To install the JMX and JConsole plugins, choose Tools > Plugins and download the module from the NetBeans Update Center.

Resources

  • NetBeans help contents (Help > Help Contents > JMX). This help is also available from Wizards.

Exercise 1: Creating the NetBeans sample Anagram Game project

The goal of this exercise is to create a runnable Java Project. The Anagram game is a Swing Application that displays a scrambled word to the user and waits for the user to solve the anagram.

  1. Choose File > New Project (Ctrl-Shift-N).

  2. Select the Samples > Java category.

  3. Select the Anagram Game project. Click Next.

  4. In the Project Name and Location panel, set the project location or keep the default value if it suits you. Select "Set as Main Project" checkbox if not selected because it will make subsequent actions easier. Click Finish.

When you click Finish the IDE creates the Anagram Game project and displays the project in the Projects window.

  1. Right-click the AnagramGame project and select Properties.

  2. Select the Sources category and confirm that the Source/Binary format is set to JDK 7 or JDK 8. Click OK.

Note. To select JDK 7 or JDK 8, the Java Platform for the AnagramGame project must also be at least JDK 7 or JDK 8, respectively. You can change the Java Platform for the AnagramGame in the Libraries category in the Properties window.

  1. Right-click the Anagram Game project node and choose Run.

When you choose Run, the IDE builds and launches the Anagram Game application.

Exercise 2: Creating the AnagramsStats JMX Standard MBean and its Management interface

The goal of this exercise is to create a skeleton JMX Standard MBean, which is composed of its implementation class and its management interface.

Perform the following steps to create the JMX Standard MBean.

  1. Confirm that the Anagram Game project is set as the main project.

  2. Choose File > New File (Ctrl-N).

  3. From the JMX category, select Standard MBean. Click Next.

jmx newfile
Figure 2. Standard MBean file type in New File Wizard
  1. Enter the following information Name and Location panel:

    • Class Name: AnagramsStats

    • Location: Source Packages (default)

    • Package: com.toy.anagrams.mbeans

    • Description: Monitoring and Management of the Anagrams Game

jmx newmbean
  1. Click Finish.

When you click Finish the AnagramsStats MBean class and AnagramsStatsMBean MBean interface are generated in the com.toy.anagrams.mbeans package of the AnagramGame project. These are now several empty skeletons that you will populate in the next exercise.

Exercise 3: Adding attributes, operation and notification to the AnagramsStats JMX Standard MBean

The goal of this exercise is to populate the generated MBean skeleton, so that it monitors the time spent by the user to solve a new anagram and a JMX notification is sent each time an anagram is solved.

The MBean will contain the following:

  • Two Attributes named LastThinkingTime and NumResolvedAnagrams

  • An Operation named resetAll .

  • A notification of type AttributeChangeNotification . This notification is emitted when LastThinkingTime is updated.

Perform the following steps to populate the MBean skeleton.

  1. Open the AnagramsStats.java MBean implementation file in the NetBeans editor.

  2. Right-click in the source editor and select JMX > Add MBean Attributes in the popup menu.

  3. Add the LastThinkingTime attribute by clicking the Add Attribute button and supplying the following information.

    • Attribute Name: LastThinkingTime

    • Type: int

    • Access: ReadOnly

    • Description: Elapsed time to solve last anagram

Note. Do not click OK yet!

  1. Click Add Attribute again and add the following NumSolvedAnagrams attribute. Click OK.

    • Attribute Name: NumSolvedAnagrams

    • Type: int

    • Access: ReadOnly

    • Description: Number of solved anagrams

jmx addattribute

The necessary code to expose the read only LastThinkingTime and NumSolvedAnagrams attributes is generated in both the AnagramsStats MBean class and its interface.

You can see the private fields declaration and the public getter methods. More precisely, looking at the members view and at the generated code, you will notice that the getLastThinkingTime and getNumSolvedAnagrams methods are generated both in the AnagramsStats class and in its AnagramsStatsMBean interface. The private fields lastThinkingTime and numSolvedAnagrams of type int were also generated and will be used to store the actual attribute values.

Next you will add three more attributes to keep track of the minimum and maximum thinking time the user took, and of the current anagram being proposed to the user.

  1. Right-click in the source editor and select JMX > Add MBean Attributes in the popup menu.

  2. Click the Add Attribute button and add the following attributes.

Attribute Name

Type

Access

Description

MinThinkingTime

int

ReadOnly

Minimum elapsed time to solve an anagram

MaxThinkingTime

int

ReadOnly

Maximum elapsed time to solve an anagram

CurrentAnagram

String

ReadOnly

Current anagram to solve

The dialog box should be similar to the following image.

jmx addattribute2
Figure 3. Add Attribute dialog after adding 3 more attributes

Note. Notice that the attributes that you already created are listed in the dialog box.

  1. Click OK and save your changes.

  2. Right-click in the source editor and select JMX > Add MBeans Operations in the popup menu.

  3. Click Add Operation and add the resetAll() operation and specify the following details. Click OK.

    • Operation Name: resetAll

    • Return Type: void

    • Parameters: (leave empty)

    • Exceptions: (leave empty)

    • Description: Reset MBean state

jmx addoperation
Figure 4. Adding resetAll operation in Add Operation dialog

After you click OK you can see that the necessary code to expose the resetAll operation was generated in both the AnagramsStats MBean class and its interface.

  1. Right-click in the source editor and select the JMX > Implement NotificationEmitter interface in the popup menu.

  2. Specify the following details in the Implement NotificationEmitter interface dialog box.

    • Select Generate Delegation to Broadcaster. All methods declared by the NotificationEmitter interface will be implemented by delegating to a notification broadcaster. A notification broadcaster simplifies the way the MBean will send notifications.

    • Select Generate Private Seq Number and Accessor. Some code will be generated to handle the unique sequence number value that must be added to each notification that is sent.

    • Click Add Notification. Specify the following details in the Notifications table.

    • Notification Class: javax.management.AttributeChangeNotification

    • Notification Type: (it is automatically set to ATTRIBUTE_CHANGE )

    • Description: Anagram is Solved

jmx changenotification
Figure 5. Adding change notification in Implement NotificationEmitter dialog

Click OK.

You can see that the necessary code to implement the NotificationEmitter interface was generated in the AnagramsStats MBean class. You can see how the generated implementation delegates the handling of notifications to the NotificationBroadcasterSupport class.

  1. Save your changes.

In this exercise you learned how to add attributes, operations and notifications emission to an MBean using the JMX Wizard module. The steps needed to populate your MBean with the necessary infrastructure to expose the management information you want are now finished. You now need to add internal logic to the AnagramsStats MBean class implementation, then build the bridge between the MBean and the Anagram Game application.

Exercise 4: Adding implementation code to the AnagramsStats JMX Standard MBean

In this exercise you will add some internal logic to the AnagramsStats MBean class implementation.

Perform the following steps to add the implementation code.

  1. The attributes already have their private fields declared, and nothing needs to be added to their getter methods.

  2. The resetAll() method needs to be implemented. The generated body is empty. When resetAll() is called, we simply set all counters to 0. Add the following lines of code (in bold) in the resetAll() method body:

public void resetAll() {
    *minThinkingTime = 0;
    maxThinkingTime = 0;
    lastThinkingTime = 0;
    numSolvedAnagrams = 0;*
}
  1. You also need to add some implementation code that will do the following:

    • calculate the thinking time the user took to solve the last anagram,

    • calculate the minimum and maximum thinking times,

    • increment the counter of solved anagrams,

    • know wich is the current anagram,

    • create and send a notification when an anagram is solved.

For that purpose you will add a private field startTime to store the time at which the last anagram was presented to the user, two methods startThinking() and stopThinking() to perform the operations listed above, and a setCurrentAnagram() method.

Add the following code to AnagramsStats.java , e.g. at the end of the class implementation.

/*
 * Methods exposed to Anagrams application to feed management with data.
 */

//Stores the time at which a new anagram is proposed to the user.
private long startTime;

/**
 * A new Anagram is proposed to the user: store current time.
 */
public void startThinking() {
    startTime = System.currentTimeMillis();
}

/**
 * An Anagram has been resolved.
 */
public void stopThinking() {

    //Update the number of resolved anagrams
    numSolvedAnagrams++;

    // Compute last, min and max thinking times
    lastThinkingTime = (int) (System.currentTimeMillis() - startTime) / 1000 ;
    minThinkingTime = (lastThinkingTime < minThinkingTime || minThinkingTime == 0) ?
                      lastThinkingTime :
                      minThinkingTime;
    maxThinkingTime = (lastThinkingTime > maxThinkingTime) ?
                      lastThinkingTime :
                      maxThinkingTime;

    //Create a JMX Notification
    Notification notification = new Notification(AttributeChangeNotification.ATTRIBUTE_CHANGE,
            this,
            getNextSeqNumber(),
            "Anagram solved: " + currentAnagram);

    // Send a JMX notification.
    broadcaster.sendNotification(notification);
}

/**
 * Set latest anagram which has been computed by the Anagram application
 */
public void setCurrentAnagram(String currentAnagram) {
    this.currentAnagram = currentAnagram;
}

Note that the three methods startThinking() , stopThinking() and setCurrentAnagram() are not part of the MBean management interface, because they are not declared in the AnagramsStatsMBean interface, but they are public because they will be called by the Anagram Game application to tell the MBean each time that a new anagram is presented to the user and when it is solved, and which is the current anagram. So, they are a necessary part of the bridge between the application and our MBean.

Notice also how a JMX notification of type ATTRIBUTE_CHANGE is sent each time an anagram is solved.

You are now done with the MBean implementation. In this section you added code and methods to allow the following:

  • internal MBean state updates

  • calls from the application

  • sending of JMX notifications

Exercise 5: Connecting Management and the Application Together

In this exercise, we will add code to the Anagram Game application so that it can access the MBean to pass management information.

Perform the following steps to

  1. Open Anagrams.java in the editor.

The Anagrams class in the com.toy.anagrams.ui package is the main class of the Anagram Game application. The file opens in the Editor’s Design view because the Anagrams class is also the User Interface class.

  1. Click the Source button at the top of the Editor window to edit the class in the Source view.

  2. Add the following empty initManagement() private method to the Anagrams class: after the Anagrams constructor.

/**
 * JMX initialization:
 * Create and register Anagrams MBean in Platform MBeanServer.
 * Initialize thinking time and current anagram.
 */
private void initManagement() throws Exception {

}
  1. Add the following call to the initManagement() method at the end of the Anagrams class constructor before the enclosing curly brace marking the end of the constructor.

//JMX Management initialization
initManagement();

You also need to add a throws Exception clause to the Anagrams() constructor and surround the statement new Anagrams().setVisible(true); with a try-catch in the Main() method to compile. You can see the suggestion glyph in the left margin of the editor. You can place your insert cursor in the line in the code and type Alt-Enter to invoke the code hint in the source editor.

jmx initmanagement try
Figure 6. Code hint to add try-catch

Here is what you should see at this stage [click to view larger image]:

jmx initmanagement sm

  1. We now add the MBean registration code to the initManagement() method, using the JMX Module MBean registration wizard:

In the Anagrams.java source editor window, right-click inside the initManagement() method body, select the JMX submenu and then the "Generate MBean Registration…​" action. In the "Instantiate and Register MBean" panel that shows up, keep the "Register Existing MBean" radio-button selected, click the Browse button, choose the AnagramsStats MBean class and click OK in the Browse panel. You should now see:

jmx registermbeandialog

No need to change the automatically specified MBean Object Name and Constructor. Click OK, and you will see the generated MBean registration code in the initManagement() method body.

Best practice for naming your MBeans

  • When naming your MBean, use the " type= " key in the Object Name. The value of this key should be the MBean class (in our case AnagramsStats ).

  • In the case of a singleton MBean (an MBean that has a single instance within your application), having this unique key is sufficient for naming purposes.

  • Avoid creating too many domain names. Use your application Java package names. You can also use the default domain name: not specifying a domain before the ObjectName " : " separator implicitly references the default domain.

Applying best practices will make the way you name your MBeans more formalized.

So, the ObjectName created by default in our case above is: com.toy.anagrams.mbeans:type=AnagramsStats

In the context of this tutorial, an extra step is required. You want the application to have access to the class implementing the management interface ( AnagramsStats ). This is not a general rule but it can be useful when your application needs to push data to an MBean. In this case, the startThinking() , stopThinking() and setCurrentAnagram() methods are not management methods but are used by the Anagrams Game application to notify the MBean that some events have occured. In turn, the MBean updates its state. In order to make AnagramsStats accessible from the Anagrams UI class, we need the Anagrams class to keep a direct reference to the instance of the AnagramsStats MBean.

Therefore, you need to make the following changes to the code of the Anagrams.java file.

  1. Add the following private field to the Anagrams class.

    // Reference to the AnagramsStats MBean
    private AnagramsStats mbean;
  1. Initialize the reference to the AnagramsStats MBean in the initManagement() method by modifying the generated MBean Registration code so that it reads:

private void initManagement() throws Exception {
    try { // Register MBean in Platform MBeanServer
         *mbean = new AnagramsStats();*
         ManagementFactory.getPlatformMBeanServer().
                registerMBean(*mbean*,
                new ObjectName("com.toy.anagrams.mbeans:type=AnagramsStats"));
    } catch (JMException ex) {
        *ex.printStackTrace();*
}
  1. Initialize the AnagramsStats MBean state: when the Anagrams Game application starts up, an anagram is immediately displayed, so we need to pass to the MBean the anagram string value and to start computing thinking time. Copy and paste the lines below at the end of the initManagement() method:

       // When the Anagrams game is first displayed, a word is proposed to the user.
       // We must start time computing and set the current anagram
       mbean.startThinking();
       mbean.setCurrentAnagram(wordLibrary.getScrambledWord(wordIdx));

Here is what you should see at this stage [click to view larger image]:

jmx initmanagement2 sm

You now need to add code to track the user’s anagram solving experience.

  1. Locate the nextTrialActionPerformed() method and paste the following code at the end of the nextTrialActionPerformed() method.

    //Update management statistics and values
    try {
        mbean.setCurrentAnagram(wordLibrary.getScrambledWord(wordIdx));
        mbean.startThinking();
        } catch (Exception e) {e.printStackTrace();}

Each time that a new anagram is proposed to the user, the code tells the MBean which anagram it is and to start counting the user thinking time.

  1. Locate the guessedWordActionPerformed() method and add the following lines to the code. Save your changes.

    //Update management stats
    try {
        mbean.stopThinking();
    } catch(Exception e) {e.printStackTrace();}

The stopThinking() method in the MBean is called each time that an anagram is guessed correctly.

You should now see the following in the editor [click to view larger image]:

jmx stopthinking sm

You have now finished linking the JMX management layer to the application layer. In the next section you will build and run the Anagrams Game application and look at the exposed management information through the JConsole GUI.

Exercise 6: Running the Application with JConsole

In this exercise, you will learn how to build and run your project, and connect JConsole to visualize the JVM state, as well as the application MBeans.

Perform the following steps to run the application and view the management information.

  1. A single step performs these three tasks: simply click the "Run Main Project with Monitoring and Management" button in the toolbar (  run project24)

You can also invoke the action from the Run menu in the main menu.

Note. The first time that you build and run the application the IDE displays a warning dialog that informs you that the build.xml files will be updated. You can click OK in the dialog.

jmx firsttime
Figure 7. Warning dialog when monitoring application for the first time

You can follow the execution in the Output window.

jmx compiling
Figure 8. Output window displaying process

The IDE will build and launch the Anagram game and will automatically open the JConsole window.

jmx anagram
Figure 9. Anagram Game

Notes. You might see a Connection Failed warning in the Java Monitoring & Management Console when the console attempts to connect to the Anagram Game process. For this tutorial you can click Insecure when you are prompted to authorize the connection.

  1. Select the MBeans tab in the JConsole window.

  2. In the tree layout in the left pane, expand all the nodes under com.toy.anagrams.mbeans .

jmx jconsole mbeans1
Figure 10. MBeans tab showing AnagramsStats node
  1. Select the Notifications node and click on the Subscribe button at the bottom so that JConsole will receive a new notification each time an anagram is solved.

  2. In the Anagrams Game window, and solve the first three or four anagrams.

The solutions to the anagrams (abstraction, ambiguous, arithmetic, backslash,…​) are contained in the WordLibrary class.

  1. In the JConsole window, and notice that it received notifications for each of the solutions.

jmx jconsole mbeans2 sm
  1. Click on the Attributes node and notice the attributes values are updated:

jmx jconsole mbeans3
Figure 11. MBeans tab showing AnagramsStats node

You can experiment with the JConsole interface and the Anagrams Game. For example, if you invoke the management operation resetAll() you will see that the MBean attribute values are reset to 0.

*And now, you are done! You did a really good job, congratulations! *

See Also

For more information, see the following: