Monitor a Java application with the Health Center API, Part 1

Get started with the Health Center API

The 2.1 release of Health Center contains a powerful API. The API allows Java™ developers to embed Health Center in their applications and harness its monitoring power to troubleshoot problems. In Part 1 of this two-part article, you learn to use the Health Center API and to monitor for deadlocks in a running Java application. Part 2 uses the deadlock detection application that is developed in this article and adds a method-profiling view to show where the application spends most of its CPU cycles.

Share:

Toby Corbin, Software Engineer, IBM  

Toby CorbinToby Corbin is lead developer of the Health Center monitoring tool; he also develops other consumability tooling within the IBM Java Technology Centre. He joined IBM in 2001 and, for four years, developed national language support and globalization of the Java Runtime Environment. Toby developed the Swing and AWT libraries for two years.



26 February 2013

Also available in Chinese Russian Japanese Vietnamese Spanish

Have you ever had your app server hang for apparently no reason, or a Java application become unresponsive? Does your application run out of memory or perform poorly? With the Health Center, you can troubleshoot these kinds of problems more easily.

Monitoring and diagnosing problems with Health Center

The IBM® Monitoring and Diagnostics tools for Java - Health Center (Health Center) is a free, low-overhead diagnostic tool and API for monitoring an application that runs on an IBM Java virtual machine (JVM). With the Health Center, you can assess the status of a running Java application quickly by providing information to identify and help resolve problems. You can:

  • Identify if native or heap memory is leaking
  • Discover which methods are taking the most time to run
  • Pin down I/O bottlenecks
  • Visualize and tune garbage collection
  • View any lock contentions
  • Analyse unusual WebSphere® Real Time events
  • Monitor your application's thread activity
  • Detect deadlock conditions
  • Gather class histogram data

The latest release of Health Center is a powerful new API that you can use to write your own monitoring tool. The days of troublesome, hard-to-find problems are now numbered.

In this article, learn to write a monitoring tool that checks an application for deadlock conditions. Then, apply these principles to write more in-depth tools, query anything from garbage collection activity to method profiling, and work out where your application spends its CPU cycles.

System requirements

The Health Center API bundle requires a minimum of Eclipse 3.4 or Eclipse 4.x.

Installing the API package into Eclipse

The IBM Monitoring and Diagnostics tools are normally installed in the IBM Support Assistant (ISA). To embed Health Center in your application and code against it using the API, first install it into your Eclipse environment. To do that, follow these steps:

  1. Start the Eclipse development environment.
  2. Go to Help -> Install New Software.
  3. Add the ISA update site as a new site.
    1. Click Add.
    2. Enter the ISA Update site in the name box.
    3. Enter this URL in the location box: http://public.dhe.ibm.com/software/isa/isa410/production/. This action starts a search of all the available tools and takes a few minutes.
  4. Enter Health Center in the search box
  5. Select the package Health Center Core Feature and click Next (see Figure 1):
    Figure 1. List of available software to install
    Screen capture of available software to install
  6. Verify the installation details and click Next.
  7. Read and accept the license terms and then click Finish. These steps install the Health Center Core feature into your Eclipse IDE. You are ready to code against the API.
  8. Verify the installation details and click Next.

Using the API, write a simple rcp to detect a deadlock. First, create a new plug-in project in Eclipse and add the Health Center API as a dependency. To do that, follow these steps:

  1. Go to File -> New -> Project -> Plug-in Project.
  2. Give the project a name such as HC_Deadlock. Click Next.
  3. Clear the Generate an activator check box. When asked if you want to create a rich client application, click Yes. Click Next (see Figure 2):
    Figure 2. Plug-in project options
    Screen capture of plug-in project options
  4. Click Next. At the template screen, select the Headless Hello RCP. Click Finish.

Next, add the Health Center API package as a dependency to the new project. Follow these steps:

  1. To add the API import to the manifest, open the MANIFEST.MF file under the META-INF in your new project (see Figure 3):
    Figure 3. Package Explorer plug-ins
    Screen capture of Package Explorer plug-ins
  2. Select the Dependencies tab and click Add. In the Select a Plug-in field, type healthcenter.api into the search. Select the com.ibm.java.diagnostics.healthcenter.api plug-in—note that the version number might be different (see Figure 4):
    Figure 4. Health Center API plug-in selection
    Screen capture of Health Center API plug-in selection
  3. Click OK. Repeat the exercise from the Select the Dependencies tab step. This time, add org.eclipse.ui—again The version number might be different (see Figure 5):
    Figure 5. Plug-in selection of org.eclipse.ui
    Screen capture of plug-in selection of org.eclipse.ui
  4. Click OK, and then save the file.

The API plug-in is now included in your application and you can start to code against it.


Testing against a deadlock application

Before you can write a deadlock monitoring tool, you want something to monitor. Listing 1 shows the source code for a simple application that gets a deadlock:

Listing 1. A simple application with a deadlock
public class GenerateDeadlock {
   AThread t1 = null;
   AThread t2 = null;
   AThread t3 = null;

   static class AThread extends Thread {
      Object hold;
      Object grab;

      AThread(String name, Object hold, Object grab) {
         super(name);
         this.hold = hold;
         this.grab = grab;
      }

      private void delay(long time) {
         try {
            Thread.sleep(time);
         } catch (InterruptedException e) {
         }
      }

      private void grabLocks() {
         System.out.println("Thread " + this + " about to hold " + hold);
         synchronized (hold) {
            System.out.println("  Thread " + this + " about to grab "
                  + grab);
            delay(5000);
            synchronized (grab) {
               System.out.println("    Thread " + this
                     + " got both monitors");
               delay(1000000);
            }
         }
      }

      public void run() {
         System.out.println("Thread " + this + " starting");
         for (int i = 0; i < 200000; i++) {
            grabLocks();
         }
         System.out.println("Thread " + this + " completed");
      }
   }

   private void createDeadlock() {
      System.out.println("Force 3 thread deadlock");
      String s1 = "obj 1";
      String s2 = "obj 2";
      String s3 = "obj 3";
      t1 = new AThread("Thread 1", s1, s2);
      t2 = new AThread("Thread 2", s2, s3);
      t3 = new AThread("Thread 3", s3, s1);
      t1.start();
      t2.start();
      t3.start();
   }

   public static void main(String[] args) {
      GenerateDeadlock d = new GenerateDeadlock();
      d.createDeadlock();
      try {
         Thread.sleep(1000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      System.out.println("Press a key to exit");
      try {
         System.in.read();
         System.exit(0);
      } catch (java.io.IOException e) {
      }
   }
}

Health Center has two parts. The first part is the Health Center agent, which loads with the application you want to monitor. The agent provides access to the data in the JVM, which the second part of Health Center—the client— then uses. The API gives you access to this client, which is normally started from ISA. Embed the client in your application to connect to an application that was started with the Health Center agent and get access to all the data that the Health Center client monitors and displays. The API does not provide a GUI, but instead makes all the data available for use in your own application. Figure 6 shows an overview of where the Health Center client and agent are located when they are installed in ISA and the JVM:

Figure 6. Locations of the Health Center client and agent when they are installed in ISA and the JVM
Diagram of the locations of the Health Center client and agent in ISA and JVM

Start the program in Listing 1 with the Health Center agent attached to it. It also requires a minimum IBM Java level of Java 5 SR8, Java 6 SR1, or Java 7. You can download the IBM developer kits.

To start the application with the agent using Java 5 SR10 and later, Java 6 SR5 and later, and Java 7, use this command (see Figure 7):

java - Xhealthcenter GenerateDeadlock

For Java 5 SR9 and earlier, or Java 6 SR4 and earlier, use this command:

java - agentlib:healthcenter - Xtrace:output=healthcenter.out GenerateDeadlock
Figure 7. Running the GenerateDeadlock program
Screen capture of command line window showing the GenerateDeadlock program

The agent is included automatically from Java 5 SR9 and Java 6 SR3. For the latest versions of the agent and instructions on how to update it, visit Health Center - Installing the Health Center agent.


Coding the deadlock monitoring application

You're ready to modify the basic Hello RCP World application and turn it into a deadlock detection tool using the Health Center API. Open the file that is called Application.java (see Figure 8):

Figure 8. Location of Application.java code
Screen capture of the location of Application.java code

Setting up the connection details

First, get a ConnectionProperties object, which has the details of the application you want to connect to. The default object is set to use localhost and port 1972, but you can change these values (and add security) in the constructor and the class methods:

ConnectionProperties hcConn = new ConnectionProperties();

When you have the ConnectionProperties object, connect to the application that you want to monitor, which is already started with the Health Center agent. Make a call to the static HealthCenterFactory.connect(hcConn, true) method. This call returns a HealthCenter object, which is the direct connection into Health Center and allows access to all the data that Health Center is monitoring. The connect call effectively starts an instance of Health Center in your application and starts collecting data:

HealthCenter hcMon = HealthCenterFactory.connect(hcConn,true);

Getting at the data

Now that you have the HealthCenter object, you can query the data. The API is laid out similarly to the GUI: the first step after it acquires a HealthCenter object is to make the call at the data type of interest to you. For this example, you want to check for deadlocks, which are part of the ThreadsData class. You can access with the getThreadsData() method on the HealthCenter object, as follows:

ThreadsData hcThreadsData = HealthCenter.getThreadsData();

The ThreadsData class has a deadlockDetected() method that returns true if a deadlock is detected. By polling this method, you can be notified if a deadlock occurs:

if(hcThreadsData.deadlockDetected()) {
      do something
}

Accessing the recommendation and analysis engine

Health Center has a built-in recommendation engine that provides all the analysis and returns the findings. You normally see these results normally see in the Analysis and Recommendations panel when you run the full version of Health Center (see Figure 9):

Figure 9. Analysis and recommendations panel in Health Center
Screen capture of Health Center analysis and recommendations panel

To query any of the recommendations, several methods are available to you. getAllRecommendations() returns an array of all the recommendations, but you can query critical problems only with the getCriticalRecommendations() call, which is the one to use on the ThreadsData object:

String[] hcThreadsRec = hcThreadsData.getCriticalRecommendations()

Seeing the full source code

The previous five calls are necessary to embed Health Center in your application and check for deadlocks in the application you want to monitor. Listing 2 shows the full source code with those calls in use:

Listing 2. The full source code shows five calls in use
package deadlockdemo;

import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;

import com.ibm.java.diagnostics.healthcenter.api.ConnectionProperties;
import com.ibm.java.diagnostics.healthcenter.api.HealthCenter;
import com.ibm.java.diagnostics.healthcenter.api.factory.HealthCenterFactory;
import com.ibm.java.diagnostics.healthcenter.api.threads.ThreadsData;

/**
 * This class controls all aspects of the application's execution
 */
public class Application implements IApplication {
   HealthCenter hcMon;

   public Object start(IApplicationContext context) throws Exception {
      ConnectionProperties hcConn = new ConnectionProperties();
      hcMon = HealthCenterFactory.connect(hcConn, true);
      try {
         System.out
               .println("Waiting for 10 seconds to allow initial data to be
                        parsed from the connection");
         Thread.sleep(10000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      checkForDeadlock();
      return IApplication.EXIT_OK;
   }

   public void stop() {
      // nothing to do
   }

   public void checkForDeadlock() {
      while (!detectDeadlock()) {
         try {
            Thread.sleep(5000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   private boolean detectDeadlock() {
      ThreadsData hcthreadsData = hcMon.getThreadsData();
      if (hcthreadsData == null) {
         System.out.println("No threads yet");
      } else {
         if (hcthreadsData.deadlockDetected()) {
            Display display = new Display();
            Shell shell = new Shell(display);

            MessageBox mb = new MessageBox(shell);
            String deadlockMessage = new String();
            String[] hcThreadsRec = hcthreadsData
                  .getCriticalRecommendations();
            for (String rec : hcThreadsRec) {
               deadlockMessage = deadlockMessage + rec + "\n";
            }
            mb.setMessage(deadlockMessage);
            mb.setText("Deadlock detected");
            mb.open();
            display.dispose();
            return true;
         }
      }
      return false;
   }
}

Monitoring for deadlocks

You now have the deadlock-monitoring application and the deadlock-infected program running in the background. Messages indicate the deadlock (see Figure 10):

Figure 10. Deadlock detected results panel
Screen capture of deadlock detected results panel

Conclusion

This article covered the basics of how to start with the Health Center API and then write a monitoring tool that checks an application for deadlock conditions. You can apply these techniques to extract and use any of the data inside Health Center. In Part 2, you'll build on these concepts and add a method-profiling view in the deadlock detection application to show where the application spends most of its CPU cycles.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Java technology on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=859510
ArticleTitle=Monitor a Java application with the Health Center API, Part 1
publish-date=02262013