Using a JMX compliant monitoring console provides useful information on performance and resource consumption of running applications such as thread usage, memory consumption, details about class loading, runtime compilation, and the operating system. In this article we will focus on giving some insight on monitoring the memory consumption of an application. This means providing high-level diagnosis on problems associated with memory management.
You need a JMX compliant monitoring tool to 'observe' the application. In this case we will use the jconsole application which is shipped since the Java Sun JDK 1.5 (in its bin directory); but you can use other clients, such as MC4J Management Console.
If you are using a Windows application jconsole, it will display all the Java applications you can connect to (Local Tab of the connection tab). For a Web Application you will need to connect using the Remote Tab specifying host and port; click here for more information. Once you have connected through JMX to your application, memory consumption and related information can be checked in:
- Memory Section of the Summary Tab.
- Memory Tab: displays information on memory consumption and memory pools.
- MBeans Tab: under the java.lang Managed Beans section.
The first thing to do is to define the Virtual Machine class that will be used to execute the Java Application. By default when the Java interpreter is executed, it does some checking in the host machine to set basic parameters such as set memory configuration, garbage collector, compiler and so on. This smart tuning is referenced as ergonomics and sets that the application will be running in Server\Client class machine.
Although the Server and the Client VMs are similar, the Server VM has been specially tuned to maximize peak operating speed. It is intended for executing long-running server applications, which need the fastest possible operating speed more than a fast start-up time or smaller runtime memory footprint.
On the other hand, the Client VM offers improved runtime performance for applications and applets. It has been specially tuned to reduce application start-up time and memory footprint, making it particularly well suited for client environments.
Tip: Use the Server-class machine for three-tiers and Web applications and client-class machine for applets and two-tier applications. Using jconsole you can check the VM Tab to obtain which Java Virtual Machine is used. For example, the figure below shows a jconsole screenshot monitoring an Apache Tomcat 5.5 installation; a server -class machine is used.
To understand the information about memory detailed through the JMX agent, we need some basic understanding about memory management in the Java Sun Virtual Machine, how it is assigned and handled.
Within jconsole you can check the Memory Tab, which displays memory use vs time for each memory pool (heap and non-heap memory, and for specific memory pools).
Using the Chart option you can switch through the available memory pools. The bar chart on the lower right-hand side shows the memory consumed by the memory pools in Heap and Non-heap memory. The bar will turn red when the memory used exceeds the memory usage threshold.
Tip: Query each memory pool and assignments to obtain at least the following information:
- Memory usage.
- Peak memory usage.
- Usage Threshold.
- Collection Usage Threshold (only supported by some garbage-collected memory pools).
Based on this information, it may be useful to modify some memory parameters such as:
- Heap Sizing.
- Permanent Generation Size.
Two important parameters to take into account are:
- Initial Heap Size.
- Maximum Heap Size.
As the Virtual Machine at startup uses a self tuning mechanism (described here) it is recommended to explicitly set memory command line options to the Virtual machine to ensure the memory assigned to the application is enough. In that case you can use the -Xms<size> and -Xmx<size> options to set initial and maximum Java heap size.
For example, using Client-class machines the default Maximum Heap size is 64MB; which may be OK for an applet but for a desktop application it could be too small.
Tip: If you want to know the memory assigned by the virtual machine when no command line options are passed to the Virtual Machine, check the Details area of the JConsole Memory Tab; it shows the following useful information:
- Used: the amount of memory currently used, including the memory occupied by all objects, both reachable and unreachable.
- Committed: the amount of memory guaranteed to be available for use by the Java VM.
- Max: the maximum amount of memory that can be used for memory management.
- GC time: the cumulative time spent on garbage collection and the total number of invocations.
The Permanent Generation memory pool is the area of heap that loads all the reflective data of the Virtual machine itself, such as class and method objects.
Configuring the size of the Permanent Generation can be important for applications that dynamically generate and load a very large number of classes such as servlets.
Usually a sign that this parameter must be changed occurs when an OutOfMemory: Perm gen Space occurs.
There is no right way to size generations; the best choice is determined by the way the application uses memory as well as user requirements. For this reason the JVM's default choices may not be optimal, and may be overridden by the user in the form of command line options. In that case the permanent generation may need to be increased using the option -XX:MaxPermSize= <N>; which by default allocates up to 64MB.
Tip: All Virtual Machine arguments passed to the Virtual Machine can be checked in the VM Information area of the JConsole VM tab.
Now that some basic information for Memory Management using JConsole has been explained, it is recommended to monitor an application under different loads so you can get important measures on how your application works, for example:
- How memory is being used by the application.
- How the application reacts to different workloads being imposed, how much memory is used, for example.
- Detect potential memory leakage.
Tip: Concentrate on the different Chart types available in the JConsole Memory Tab and the Bar graph in the lower right Details Section. For example the following figure shows the Heap memory usage of a web application running for several hours using Apache Tomcat.
Some useful information taken from the figure below:
- The Maximum heap size is 512MB.
- The used memory never gets higher than 260MB; the Garbage Collector is executed freeing available memory when the application is close to this threshold.
The use of a JMX client provides very useful information on performance and resource consumption of running applications. Even though a reasonable understanding of the JVM is needed to understand most of the information exposed by JMX, you can start focusing on some 'specific spots' such as memory usage (explained here) or the GeneXus connections pool which can help in the 'diagnosis' of a possible problem.
Understanding the information detailed by a JMX Client will not only help you improve your applications, but it will help you understand all about the environment in which your application runs. You will also be able to analyze thread usage and details about class loading, change certain application\server properties at runtime and trigger some operations\notifications based on the value of some variables.
This article applies to Java Sun VM 1.4.x version or higher.
Related articles in the Community Wiki:
More general information: