IBM WebSphere Developer Technical Journal

Writing PMI applications using the JMX interface


To help identify performance problems and help tune an environment running Web applications, IBM® WebSphere® Application Server collects performance data and provides interfaces that allow external applications to monitor that performance data. Data is collected on the WebSphere Application Server run time and on customer applications through the Performance Monitoring Infrastructure (PMI). PMI data is then exposed to users via various interfaces.

Currently, there are three PMI data interfaces available:

  • the PMI client
  • the performance servlet
  • the Java™ Management Extension (JMX) interface.

The PMI client and servlet interfaces are available in WebSphere Application Server V4 and V5. The JMX interface is new with WebSphere Application Server V5.

WebSphere Application Server contains a basic viewer for looking at PMI data, the Tivoli® Performance Viewer (TPV), with which users can look at various graphs and values of PMI counters. Many third party tools that use these PMI interfaces are also available, often used for identifying thresholds for PMI counters and for helping customers tell when a Web site is experiencing a performance problem.

This article explains the relationship of PMI, JMX MBeans, and the performance data framework defined by the J2EE management specification (see Related topics) We will demonstrate how to access the WebSphere Application Server PMI data using the JMX interface, which includes how to instantiate an AdminClient instance, how to get the JMX MBeans required for PMI access, how to set PMI instrumentation levels, how to get PMI data, and more. A downloadable sample program that collects PMI data using the JMX interface is also included.

What is PMI?

The Performance Monitoring Infrastructure is the underlying framework in WebSphere Application Server that gathers performance data from various run time resources such as JVM and Thread Pools, and application components such as servlets and Enterprise Java Beans (EJBs). Some examples of available WebSphere Application Server V5 counters include:

  • average response time
  • number of total requests
  • thread pool size
  • JVM heap size.

PMI collects this data from various components in the server and organizes them into a tree structure. Figure 1 is a snapshot from the Tivoli Performance Viewer showing the tree structure rooted at a server, where a tree node directly under the server is called a PMI module (marked with a red circle) and a tree node under a module is called a PMI submodule, which can be recursively organized by submodules.

Each PMI module and submodule contains a list of PMI data collected from the corresponding WebSphere components. Some modules and submodules collect data from run time entities, while the others aggregate the data over the run time entities. For example, PMI supplies data for individual thread pools, like the Object Request Broker (ORB) and Web container thread pools, as well as the aggregated data over individual thread pools. These PMI data are organized in the following tree hierarchy:

Thread Pool Module=>a module for data aggregated over all thread pools
.... ORB Thread Pool=>a submodule for data collected in ORB thread pool
.... WebContainer Thread Pool =>a submodule for data collected in web container thread pool.
.... other thread pool(s), if any
Figure 1. The PMI module/submodule tree structure from a TPV snapshot
Figure 1. The PMI module/submodule tree structure from a TPV snapshot
Figure 1. The PMI module/submodule tree structure from a TPV snapshot

Users retrieve PMI data through monitoring tools like Tivoli Performance Viewer (formerly called Resource Analyzer), which ships with WebSphere Application Server, and third party tools. Users can also write their own PMI applications using programmatic interfaces like the PMI client API and the JMX API. The JMX interface, new in WebSphere Application Server V5 as a server management model, allows remote data access via JMX MBeans.

In the next sections, we will introduce the relationship of PMI, J2EE performance data framework and JMX MBeans, and then step through how to use the JMX interface to find MBeans, set instrumentation level, and get PMI data. (See Related topics for information on the PMI client API.)

PMI, J2EE performance data framework and JMX MBeans

In WebSphere Application Server V5, PMI not only provides performance data for various components in the application server, but it also implements the statistical interfaces defined by the performance data framework in the J2EE management specification. These statistical interfaces include the following data types:

  • CountStatistic
  • TimeStatistic
  • RangeStatistic
  • BoundedRangeStatistic.

A Stats interface is defined to contain a list of statistical data.

PMI implements these statistical interfaces, updates various statistical data, and exposes the data through various interfaces. In WebSphere Application Server V4, PMI provided the PMI client interface that defined CpdLong, CpdStat and CpdLoad data types. (These interfaces are still supported for backward compatibility.) Table 1 describes the detailed APIs for the data types in Version 5. Note that the APIs in PMI data extend the definitions in the J2EE performance data framework, and those APIs extended by PMI are marked with *.

Table 1. Different PMI Data Types and APIs

5.0 Types Matched 4.0 Types Descriptions APIs
CountStatisticCpdLongKeeps a single current value.getCount()
TimeStatisticCpdStatKeeps total, count, min, and max. The mean (or average) can be derived from total and count.getTotalTime()
RangeStatisticCpdLoadKeeps current, min, max and the time-weighted total that can derive the average.getCurrent()
BoundedRangeStatisticCpdLoadKeeps current, min, max, lower bound, upper bound, and the time-weighted total that can derive the average.getCurrent()
StatsCpdCollectionContains a list of statistic data and optionally contains a list of Stats object from its submodules.getStatistic(int dataId)*
getStatistic(String name)

Each PMI data type has dynamic value(s) that may be updated over time, as well as static configuration information that will not change. The dynamic values include the current value, the minimum, the maximum, the total, etc. The static information includes the name, the unit, and description of the data. Table 1 shows the APIs returning the dynamic values for different types of data. For each data type, there are also common APIs returning the static information for each data. These APIs includes:

  • getName: return the name of the data
  • getUnit: return the unit of the data
  • getDescription: return the description of the data.

PMI data can be accessed via various interfaces including the JMX interface. The JMX architecture is a standard management model where business applications and resources are managed by Managed Beans (MBeans). An MBean can be a statistics provider that supplies various statistical data for the managed application and resource. PMI implements and updates the statistical data (i.e., PMI data) for the MBeans that are statistics providers. These PMI data can be retrieved on the client side using the JMX interface.

If an MBean is a statistics provider, its PMI statistical data can be retrieved from the MBean using the Stats attribute. Several MBeans providing a Stats attribute in WebSphere Application Server V5. See the WebSphere Application Server Information Center (under Performance => Monitoring Performance => Performance data organization) for a list of such MBean types.

PMI service and PerfMBean architecture

In WebSphere Application Server V5, the PMI service is available in every application server and node agent process. Before you can get PMI data, you first need to enable the PMI service, which can be done via the admin console or with admin scripting. In both cases, the application server must be restarted. In a Network Deployment environment, PMI service should be enabled in the application servers and in the NodeAgents.

An MBean called "PerfMBean" is implemented to configure the PMI service (i.e., set instrumentation levels) and provide APIs to gather PMI data from multiple MBeans in a single JMX call, as opposed to using individual MBeans. Figure 2 shows a simplified view of PMI architecture. The PerfMBean API, or individual MBean API, provides the PMI statistical data, but the PerfMBean is the only MBean that enables setting of the instrumentation level. PerfMBean can also reduce the number of remote JMX calls for getting the PMI data by handling multiple MBeans in one JMX call.

Figure 2. High level view of PMI data access
Figure 2. High level view of PMI data access
Figure 2. High level view of PMI data access

Table 2 summarizes how PerfMBean and individual MBeans can be used to configure and access PMI data. Since PerfMBean provides more extensive and efficient functions than the individual MBeans, it is typically used to develop monitoring tools.

Table 2. Different PMI Data Types and APIs

MBeans Set instrumentation level Get PMI data from a single MBean Get PMI data from multiple MBeans Get PMI data from PMI modules and submodules that have no MBeans Get static configuration information
Individual MBeansNoYesNoNoNo

Now that we have discussed the relationship between PMI data, JMX, PerfMBean, and individual MBeans, we are ready to see how the JMX interface can be used to get PMI data.

How to get PMI data via JMX interfaces

The steps for getting PMI data via the JMX interface are presented below along with some sample code. These steps will include:

  1. Create an AdminClient instance
  2. Find PerfMBean and individual MBeans
  3. Set instrumentation level
  4. Get PMI data from an individual MBean
  5. Get PMI data for multiple MBeanStatDescriptors
  6. Retrieve the static configuration information
  7. Get individual PMI counters from a Stats object.

Step 1: Create an AdminClient instance

In WebSphere Application Server V5, all the remote JMX calls are made through the AdminClient interface, which provides the client side APIs to a JMX client and delegates all the calls to the server side JMX connector through a proxy. The currently supported connectors are SOAP and RMI connectors.

To create an instance of AdminClient, you need to pass the appropriate host name, port number, and connector type. The following code sample creates an instance of AdminClient called "ac", which will be used in later steps to query JMX, get Stats from MBeans, and invoke methods on MBeans.

AdminClient ac = null;
java.util.Properties props = new java.util.Properties();
props.put(AdminClient.CONNECTOR_TYPE, connector);
props.put(AdminClient.CONNECTOR_HOST, host);
props.put(AdminClient.CONNECTOR_PORT, port);
try {
	ac = AdminClientFactory.createAdminClient(props);
} catch (ConnectorException ex) {
	System.out.println("Exception to create AdminClient: " + ex);

Step 2: Find PerfMBean and individual MBeans

Each MBean has an ObjectName, which must be found before the MBean can be used. The ObjectName(s) can be queried via AdminClient by a formatted query string. The formatted query string can optionally include properties such as domain name, node name, process name, type, name, and others. A query string may either uniquely identify a single ObjectName, or represent multiple ObjectNames with common properties. MBeans are usually categorized by their types.

If the PMI service is enabled in an application server, then there is one and only one MBean (PerfMBean) with "Perf" type in the server providing extended functions for PMI service configuration and PMI data retrieval. The following code will return the MBean ObjectName of PerfMBean in a server.

StringBuffer oNameQuery= new StringBuffer(); 
  // "Perf" can be replaced by other types to find MBeans in those types
String domainName = ac.getDomainName();
Set oSet= ac.queryNames(new ObjectName(oNameQuery.toString()), null); 
Iterator i = oSet.iterator (); 
ObjectName perfOn = null;
if (i.hasNext ()) { 

The above code can be modified by appending different properties and values to oNameQuery to query other MBean ObjectName(s) matching the query criteria. For example, if you replace Perf with Servlet, you will get a set of ObjectNames for all the servlets in the server.


Other MBean types can also be passed to find the relevant MBeans. Some types of MBeans (for example, Perf) will provide a single instance in an application server, but other types of MBeans (for example, servlets and EJBs) may provide multiple instances in an application server. In the latter case, an MBean can be further identified by its name. For example, the following line may be added to the query string to find the exact ObjectName for "myServletName".


Keep references to the ObjectNames found in this step because these ObjectNames will be used later.

Step 3: Set instrumentation level

By default, PMI instrumentation levels are set to none. Therefore, PMI data must be set to the proper instrumentation level (either programmatically, by using the admin console, or with admin scripting). Regardless of method, the level setting will take effect immediately without restarting the server.

The following code shows how to programmatically set instrumentation level for an MBean via PerfMBean: construct an MBeanLevelSpec object for the MBean by passing its ObjectName (from Step 2), an optional StatDescriptor (null in the example), and the desired level. The StatDescriptor is used to specify a subset of PMI data in this MBean and will be described later in Step 5. Note that multiple ObjectNames can be used to create an array of MBeanLevelSpecs, which can be passed to set the instrumentation level for multiple MBeans at one time.

	// First, set the parameter and signature arrays
	Object[] params = new Object[2];
	params[0] = new MBeanLevelSpec(mbeanObjectName, null, 
	params[1] = new Boolean(true); 
	String[] signature= new 
String[]{"", "java.lang.Boolean"}; 
	ac.invoke(perfOn, "setInstrumentationLevel", params, signature);

Step 4: Get PMI data from an individual MBean

If an individual MBean provides the Stats attribute, the related PMI data can be obtained by getting the Stats attribute from an MBean once the ObjectName is obtained from Step 2. Again, note that instrumentation level cannot be set via individual MBeans.

Stats aStats = (Stats)ac.getAttribute(mbeanObjectName, "Stats");

Step 5: Get PMI data from PerfMBean

In Step 4, only one Stats object from one MBean can be obtained in a single getAttribute call. To get Stats objects from multiple MBeans, getAttribute has to be called multiple times. Since getAttributes is a remote JMX call, multiple calls may incur high communication overhead. PerfMBean is designed to allow data access in a more efficient and flexible manner. PerfMBean provides the following means for data access:

Get performance data from a single MBean using PerfMBean

The following code returns the Stats object in an MBean. Since only a single MBean is passed here, it is equivalent to getting the Stats attribute from the MBean directly.

Object[] params = new Object[]{myObjectName, new Boolean(false)};
  // set true to return data in the submodules
string[] signature= new String[]{"", "java.lang.Boolean"}; 
Stats myStats =  (Stats)ac.invoke(perfOn, "getStatsObject", params, signature);

In the above code, set the Boolean parameter to true for PMI to return all the PMI data in that MBean and its submodules. For example, if you query data for a Web application and set the Boolean parameter to true, PMI data is returned for the Web application and all the servlets under the Web application. The Boolean parameter can also be set to true in the other APIs for getting PMI data.

Get performance data from multiple MBeans using PerfMBean

The following code returns the Stats objects for multiple MBeans. This is typically more efficient than getting the data separately.

ObjectName[] myOnArray;
  // myOnArray is the array of all the Mbeans you want to get PMI data
Object[] params = new Object[]{myOnArray, new Boolean(false)};
  // set true to return data recursively
String[] signature= new String[]{"[;", "java.lang.Boolean"}; 
Stats[] myStatsArray = (Stats[])ac.invoke(perfOn, "getStatsArray", params, signature);

Get performance data for a PMI module/submodule that has no MBean

Invoking the getStatsObject method allows access to PMI modules and submodules that do not have matching MBeans in the server. For example, the PMI module "threadPoolModule" is a logic group that contains the aggregated PMI data over all the thread pools. However, there is no such run time MBean for this logic group. In this case, an MBeanStatDescriptor that consists of an MBean ObjectName and a StatDescriptor is constructed for the PMI module/submodule. The ObjectName identifies an MBean, and the StatDescriptor indicates a relative path from the MBean in the PMI tree. An MBeanStatDescriptor provides PMI access in a finer granularity than an MBean. The ObjectName and StatDescriptor are also used to construct an MBeanLevelSpec in Step 3.

The following code obtains PMI data for threadPoolModule. The server ObjectName means it starts from the PMI tree root in the server, and the relative path in StatDescriptor is threadPoolModule from the root.

ObjectName serverON;
  //  this is the ObjectName for the server you want to query PMI data
StatDescriptor mysd = new StatDescriptor(new String[]{PmiConstants.THREADPOOL_MODULE});
MBeanStatDescriptor mymsd = new MBeanStatDescriptor(serverON, mysd);
Object[] params = new Object[]{mymsd, new Boolean(false)};  
String[] signature= new String[]{"",
Stats myStats = (Stats)ac.invoke(perfOn, "getStatsObject", params, signature);

If you know the ObjectName and StatDescriptor, construct an MBeanStatDescriptor directly. Otherwise, discover all the MBeanStatDescriptors via the listStatMembers method in PerfMBean. The methods listStatMembers(ObjectName) and listStatMembers(MBeanStatDescriptor) return an array of MBeanStatDescriptors for the immediate children in the PMI tree. Therefore, call the listStatMembers method recursively to get all the MBeanStatDescriptors and find the desired one. Note that StatDescriptor may be null; in that case the MBeanStatDescriptor provides the same PMI data as its ObjectName.

Get performance data for multiple MBeanStatDescriptors

This method will return an array of Stats objects for multiple MBeanStatDescriptors in a single JMX call, which is typically more efficient than multiple JMX calls. The following code shows how to use the method:

MBeanStatDescriptor[] myMsdArray;
  // myMsdArray is the array of MBeanStatDescriptors you want to get PMI data
Object[] params = new Object[]{myMsdArray, new Boolean(false)};
  // set true to return data recursively
String[] signature= new String[]{"[;",
Stats[] myStatsArray = (Stats[])ac.invoke(perfOn, "getStatsArray", params, signature);

In Step 5, we showed the different ways to call getStatsObject and getStatsArray in PerfMBean to get the desired PMI data. Using either ObjectNames or MBeanStatDescriptors, PMI data can be retrieved regardless of whether there is an MBean as the statistic provider for the data. Passing true or false to the Boolean parameter in all the getStatsXXX methods indicates whether or not the whole subtree is provided for PMI.

Step 6: Retrieve the static configuration information

To reduce the communication cost, PMI does not return static configuration information (such as data name and description) when PMI data is retrieved in Steps 4 and 5. However, you can get the static information separately and bind it with the PMI data if needed. Use the following code to get all the configuration information from the server, find the PmiModuleConfig for an MBean, and bind the Stats data with the configuration data. Cache the PmiModuleConfigs so that invocation of a remote call is not required every time.

	// get all the configs in one call and cache it in your client program
	PmiModuleConfig[] configs = (PmiModuleConfig[])ac.invoke(perfOn, 
"getConfigs", null, null);
	PmiModuleConfig myConfig = PmiClient.findConfig(configs, 
	myStats.setConfig(myConfig); // this is an API extended by PMI

Step 7: Get individual PMI counters from a Stats object

Steps 4 and 5 return PMI data as the Stats objects when using either an individual MBean or the PerfMBean. A Stats object contains a list of PMI data that implements the different data types shown in Table 1. A Stats object may optionally have a list of Stats objects when querying the data in a recursive mode (such as when the Boolean parameter is set to true). The following sample code shows how to get individual PMI counters from a Stats object. Note that WebSphere Application Server V5 packages the interfaces for the J2EE performance data framework in The following code uses the interfaces in this package. In the sample download code, we can use the WebSphere extended interfaces in the package to provide additional methods, such as getting the sub-stats.

// get all the data from the Stats object        
Statistic[] dataMembers = stat.getStatistics();
if (dataMembers != null)  {
	for (int i=0; i<dataMembers.length; i++) {
	// For each data, cast it to be the real Statistic type so that we can get the value from each Statistic.
	// Can call the following common methods without knowing the data type:     
	// getName(), getDescription(), getStartTime(), getLastSampleTime()
	// check the data type and cast the data to the right type
	if (dataMembers[i] instanceof CountStatistic) {
		// cast it to CountStatistic and call the API to get the data value
	} else if (dataMembers[i] instanceof TimeStatistic) {
		// cast it to TimeStatistic and call the API to get the data value
	} else if (dataMembers[i] instanceof RangeStatistic) {
		// cast it to RangeStatistic and call the API to get the data value


This article presented the relationship between PMI, JMX MBeans, and the J2EE performance data framework. PMI implements the J2EE performance data framework and allows data access via the JMX interface. The PerfMBean programmatically sets the instrumentation level for each PMI module. Once PMI data is enabled, the data can be obtained through either individual MBeans or the PerfMBean. Use the MBeanStatDescriptor to get PMI data from a PMI module/submodule which has no mapping MBean in the server. A more efficient way to get PMI data from multiple MBeans is to use PerfMBean to make single JMX calls, as opposed to making multiple JMX calls for individual MBeans. APIs to retrieve static configuration information and navigate the Stats object are also available.

PMI data can help with performance monitoring and tuning. For example, the performance advisors shipped in WebSphere Application Server V5.02 monitors the PMI data and provides advice for optimizing the performance by adjusting the application server configuration. Based on the performance data in each server, a monitoring tool using PMI can help with workload management, capacity planning, and generating alerts by checking the values of related PMI counters.

Downloadable resources

Related topics


Sign in or register to add and subscribe to comments.

ArticleTitle=IBM WebSphere Developer Technical Journal: Writing PMI applications using the JMX interface