The JVM provides many statistics. These statistics dispense data on the basic JVM features, such as Just-In-Time (JIT) compilation, class loading, memory allocation, and most interestingly, garbage collection.
The JVM performs JIT compilation of byte code into machine code. This action is similar to that of an interpreter like you might use for a scripting language such as Perl. It's more advanced, however, providing many optimizations that allow interpreted byte code to run nearly as fast (sometimes faster) than precompiled code. Obviously there's overhead in performing JIT compilations. Two useful statistics for measuring how much overhead your application will encounter are the number of JIT compiles and the total amount of time spent performing these compilations. (See Resources for more details on JIT compilation.)
The JVM is responsible for loading the classes in your application and classes from libraries that your application's classes use. Thus these could be classes loaded from WARs or EARs that you have deployed in Geronimo, JAR files included in your WAR or EAR, or classes from JARs loaded by the Geronimo container. The JVM can also choose to unload classes if the class has not been used for an extended period of time. This leads to several important statistics: how many classes have been loaded, how many have been unloaded, and how much time has been spent loading and unloading classes.
There is no malloc() function in Java technology because the JVM automatically allocates memory for objects. Objects are allocated from the heap; thus the amount of heap memory both used and free are two very important statistics. Monitoring your heap allocation is one of the simplest ways to detect a dreaded memory leak.
This is probably the most interesting statistic from the JVM. Just as the JVM allocates memory for your objects, it also reclaims this memory on objects that are no longer being used. There are many interesting reads on how garbage collection works, including the different algorithms you can instruct the JVM to use for its garbage collector.
There are also many interesting statistics about the garbage collector itself. The first is how often the garbage collector has been called and how much time was spent during garbage collection. Garbage collection has a lot of overhead, as it basically halts the execution of your application so it can examine your objects. Obviously, a lot of garbage collection can really slow down your application.
Other interesting statistics have to do with object generations. The garbage collector sorts objects by generation, with each generation denoting a certain number of garbage collections the object has survived. (An object that has survived numerous garbage collections is less likely to be garbage collected than an object that has survived none or few garbage collections.) Sorting objects like this allows the garbage collector to examine fewer objects, making each garbage collection quicker. Thus, the number of objects in each generation can be extremely interesting, providing an even better way to look for memory leaks and a great way to examine the impact of potential optimizations, such as object caching and pooling.
There are several JVM implementations available, but the most common one is Sun's HotSpot JVM (see Resources for a link to the technology). Starting with Java 2 Platform, Standard Edition (J2SE) 1.4.2, HotSpot was fully instrumented, providing many of the useful statistics described above. There are several ways to get this data and analyze it. After you've gotten to the statistics generated by the JVM, you can access Geronimo's JVM and analyze your applications.
The simplest way to get to some of the JVM stats is via the command line. HotSpot recognizes many command line options, several of which allow you to customize heap size and garbage collection options. You can also use the -verbose:gc option. This causes the JVM to print out lines that look like this:
[GC 70333K->65666K(98896K), 0.0007817 secs]
[Full GC 65666K->59333K(98896K), 0.0205250 secs]
The first line in the example above indicates a garbage collection occurred. A total of 70,333KB were used on the heap before the collection, and 65,666KB after. The first line also indicates that there are 98,896KB of total available space. Finally, it indicates how much time the garbage collection took -- also the amount of time your application was halted. The next line indicates the same information, but denotes a full garbage collection. A full garbage collection involves the JVM examining all objects on the heap, including those that have survived many generations, that would not be analyzed on partial garbage collections.
For even more detailed information, use the -XX:+PrintGCDetails and -XX:+PrintGCTimeStamps options. These options provide detailed information on the different generations of objects on the heap.
For something more visually interesting, you can use a specialized tool. Both open source and commercial tools are available. You can also use some tools provided by Sun for use with HotSpot. The jvmstat project contains several tools for monitoring JVM statistics. It includes a graphical tool called the Visual Garbage Collector or visualgc. It's relatively simple to use. You need Java 5 or later to run jvmstat, although it can attach and monitor any 1.4.2 or later JVM. Simply download it and unzip it (see Resources for the download link). Add it to your path, and you're ready to go. When you have a Java process started, use the jps tool to identify its JVM by typing jps. It gives you a list of running Java processes with an ID for their JVMs. You then invoke visualgc with the ID of the process you want to monitor. The jvmstat distribution includes a shell script for invoking visualgc. This works well on *nix or on Microsoft® Windows® if you have something like cygwin installed. Alternatively, you can invoke it as follows:
java -Xbootclasspath/p:%JAVA_HOME%\lib\tools.jar -jar %JVMSTAT_HOME%\jars\visualgc.jar 316
Here, the JAVA_HOME environment variable specifies where the JDK is installed, and JVMSTAT_HOME indicates where the jvmstat package is installed. The 316 on the end of the line is the ID for the JVM you want to monitor. The jvmstat package also includes a jstat tool. It provides much of the same information seen in visualgc but outputs it as text. This is great for collecting statistics that you can then drop into another program to do deep analysis on, generate reports on, and so on. This article concentrates on the visualization of these statistics using visualgc.
Listing 1 provides a short program you can run to test monitoring with jvmstat.
Listing 1. Test monitoring with jvmstat
StatGen.java
import java.util.ArrayList;
import java.util.List;
public class StatGen {
static final int MAX_BLOCK = 8*1024*100;
public static void main(String[] args) {
try{
int numLoops = 1;
if (args.length > 0){
numLoops = Integer.parseInt(args[0]);
}
System.out.println("#loops="+numLoops);
List<long[]> list = new ArrayList<long[]>(numLoops);
for (int i=0;i<numLoops;i++){
int sz = (int) (Math.random()*MAX_BLOCK);
long[] garbage = new long[sz];
if (sz % 5 == 0){
list.add(garbage);
}
System.out.println("Sleeping 0.5s");
Thread.sleep(500);
}
System.out.println("Done");
} catch (Throwable t) {
t.printStackTrace();
}
System.exit(0);
}
}
|
This is a simple program. It uses generics, so you'll need Java 5. You can easily alter it to not use generics if you like, then it will run with older JDKs. It causes memory allocation by creating randomly sized arrays of long integers. It mimics a memory leak by randomly placing some of these arrays (~20% of them) into a list. Thus the garbage collector can reclaim most of the memory allocated on each loop, but it can't reclaim the arrays that are added to the list. You can play with some of the parameters, such as the sleep size and maximum block size. It also takes a command line parameter so you can easily tell it how many loops to execute.
After you've compiled StatGen, you can start simply with java StatGen 100. This executes 100 loops. Remember, you can specify minimum and maximum heap size on the command line. Picking different minimum and maximum heap sizes will have a distinctive visual effect when running visualgc. You can also specify different garbage collection algorithms; you should get a good understanding of the differences in these algorithms when monitoring StatGen with visualgc.
Figure 1 shows some sample output of running visualgc with StatGen.
Figure 1. Running
visualgc with StatGen
Figure 2 shows the most interesting of the windows. It first shows JIT compilations. In this case, there were only three, not surprising for such a simple example. It also shows class loader information -- again, this is simple because the application is so simple.
Figure 2. Basic JVM information and heap usage
Next it shows overall garbage collection stats. You see 123 collections and a total of about 0.3 seconds spent doing garbage collection. From the first graph, you see the application had been running for about 100 seconds, so 0.3% of that time had been spent doing garbage collection.
There are also stats on the different generations. The eden space shows new objects that have never been through garbage collection. The sample code generates a lot of those, and they are quickly collected.
Notice the two survivor spaces. These are basically smaller sets of objects that have survived a few garbage collections. All of your objects are either immediately ready for collection or are never ready, so if they make it to a survivor space, they'll quickly graduate from it.
Next is the older generation. These objects have survived numerous garbage collections. You can see the steady rise, indicative of a potential memory leak. Finally, you see the permanent generation of objects that the JVM is certain will never be collected.
The histogram window (see Figure 3) shows data on survivor spaces -- not a lot going on here.
Figure 3. Histogram window showing data on survivor spaces
Geronimo and the initial build
There are several directories in the binary and source installations you downloaded earlier. The binary download includes the bare bones of Geronimo necessary to run and use Geronimo. The source download includes all the Geronimo source, including Maven build scripts to build the entire tree. First, take a look at the binary distribution and then the source distribution.
JVM statistics on Geronimo sample applications
Geronimo comes with several sample Web applications. Now that you have some tools for extracting JVM statistics from any JVM, it's easy to do this for Geronimo apps.
It's pretty interesting just to start Geronimo and monitor it with visualgc, as shown in Figure 4, Figure 5, and Figure 6.
Figure 4. Starting Geronimo and monitoring with
visualgc
Figure 5. Graph showing JIT compilations, class loader information, and garbage collection
Figure 6. Survivor Age Histogram
Starting Geronimo was done with the standard java -jar %GERONIMO_HOME%/bin/server.jar command. You can gain some immediate insight by just using the -server option on your startup command, as shown in Figure 7.
Figure 7. Using the
-server option on your startup command
Notice there are much fewer JIT compilations. That's because more classes get loaded when the JVM starts up when you use the -server option. The default startup mode is designed for quicker startup to accommodate desktop applications.
In both cases, you see a lot of long-running objects on the heap, but the number flattens out once Geronimo is completely started. This shows all the server objects being loaded, such as the various GBeans and the services they manage. The Geronimo developers will be pleased to see no signs of a memory leak though, as the old generation and permanent generation allocations flatten out.
Now you can also run some of the included Geronimo Web applications. The graph in Figure 8 shows the garbage collection action for the JSPX-XHTML sample application.
Figure 8. Garbage collection action for the JSPX-XHTML sample application
You can see the sudden rise of objects on the left, and then most of them disappear after the page is rendered, as you would expect. You can see the JIT compilations and class-loading events that also corresponded to the application running.
Now that you've seen how to access and analyze the JVM statistics generated when running one of Geronimo's sample Web applications, you can start analyzing your own applications. It's just a matter of starting up Geronimo, starting up visualgc, and then deploying and/or starting your application. Run some events through it, watch it load classes, compile bytecode, and of course, manage memory.
JVM statistics are invaluable when tuning an application. The tools provided by Sun let you quickly analyze your application, make optimizations, and see the effects of your optimizations. They also allow for experimentation with various JVM options to perform additional tuning to the application. One of the goals of Geronimo is to provide a high-performance application server, and JVM statistical analysis is a great complement in your quest for maximum application performance.
Learn
- Get an introduction to basic garbage collection theory and principles by reading "A brief history of garbage collection" (developerWorks, October 2003).
- Read "Garbage collection in the HotSpot JVM for an introduction to generation garbage collection (developerWorks, November 2003).
- Use features of Java 5 and Aspects to build tools to gain even more insight into your application's performance (developerWorks, March 2006).
- Get a comprehensive list of the various options offered by the Java HotSpot VM. This includes options for generating statistics and options for tuning your performance.
- Be sure to read "The Hotspot Virtual Machine," an in-depth article on HotSpot, which explains how things like JIT compilations affect performance and how you can use this information to tune your application.
- Check out the Java Performance Tuning resources site, which contains a huge list of resources for tuning, from books to both free and commercial tools.
- Read "Building a better J2EE server, the open source way" (developerWorks, May 2005) for a look at Geronimo's architecture and high-performance features.
- Check out The Geronimo renegade series -- it's hogging all the buzz!
- Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
- Check out the developerWorks Apache Geronimo project area for articles, tutorials, and other resources to help you get started developing with Geronimo today.
- Check out the IBM Support for Apache Geronimo offering, which lets you develop Geronimo applications backed by world-class IBM support.
- Find helpful resources for beginners and experienced users at the Get started now with Apache Geronimo section of developerWorks.
- Browse all the Apache articles and free Apache tutorials available in the developerWorks Open source zone.
- Browse for books on these and other technical topics at the Safari bookstore.
Get products and technologies
- Download the jvmstat package used in the article.
- Download Sun's HotSpot JVM.
- Download Java 5.0.
- Download Apache Geronimo, Version 1.0.
- Innovate your next open source development project with IBM trial software, available for download or on DVD.
- Download your free copy of IBM WebSphere® Application Server Community Edition V1.0 -- a lightweight J2EE application server built on Apache Geronimo open source technology that is designed to help you accelerate your development and deployment efforts.
Comments (Undergoing maintenance)





