
NetBeans IDE 4.0 Profiler Tutorial
Contributed by Gregg Sporar as part of the
Win With NetBeans comptetition
This article is intended to be used in conjuction with NetBeans Profiler, Milestone 5.
If you are using Milestone 4 please use this version.
If you are using Milestone 6 please use this version.
The NetBeans Profiler is a powerful tool that provides important information about
the runtime behavior of your application. While imposing relatively little overhead,
the NetBeans Profiler tracks CPU performance and memory usage.
This tutorial will show you how to use the Profiler with NetBeans 4.0 to:
Portions of this tutorial originally appeared in a June, 2004 Java Developer's Journal
article about JFluid,
the underlying technology used by the NetBeans Profiler. All reprinted material is used
by permission of the publisher of Java Developer's Journal.
This tutorial should take approximately one hour to complete.
Setting Up Your Environment
Installing the Profiler
The NetBeans Profiler is in beta and is available as a separate download.
To use this tutorial you must install the most recent version of the NetBeans
Profiler. Be sure to follow the NetBeans Profiler
Download & Install instructions.
Configuring Tomcat
Profiling a web application requires that the web server be run with
the JDK that is included with the NetBeans Profiler. So to use
the Profiler with the Tomcat server that is bundled with NetBeans
a small change to the way Tomcat starts is necessary. The easiest way to do this is to
modify the script that
starts Tomcat. The script is catalina.bat (on Windows) or catalina.sh (on Unix).
These scripts are located in Tomcat's bin folder; a typical location on
a Windows system would be:
C:\Program Files\netbeans-4.0\nb4.0\jakarta-tomcat-5.0.28\bin\catalina.bat
And on Unix the location will be something like:
/export/home/gs/tools/netbeans/40/nb4.0/jakarta-tomcat-5.0.28/bin/catalina.sh
- Save a copy of the script as a backup.
- Right below the large block of comments that is at the top of the file,
add a line that sets JAVA_HOME to the folder that contains the JDK included
with the NetBeans Profiler. Choose Profiler > Help > About Profiler in NetBeans
to display the folder name. Example value on Windows:
set JAVA_HOME=c:\Documents and Settings\gs\.netbeans\4.0\modules\profiler-ea-vm\
Example value on Unix:
JAVA_HOME="/home/gs/.netbeans/4.0/modules/profiler-ea-vm/"
Obtaining the required source files
This tutorial uses a web application based on the
HelloWeb project created in the
NetBeans IDE 4.0 Quick Start Guide for Web Applications. The modifications
for this tutorial include the addition of a servlet that handles the
incoming request. It creates a Java bean and then dispatches to the JSP
that creates the response. The servlet has been poorly written on purpose in order
to highlight features of the NetBeans Profiler.
You get all application files from the ProfilingTutorial.zip file.
- In your file system, create a folder for the unzipped application files. From now on,
this folder will be referred to as $UNZIPHOME.
- Click here
to download the ProfilingTutorial.zip file.
- Use an application that unzips files to unzip the ProfilingTutorial.zip
file to $UNZIPHOME.
$UNZIPHOME now has web and src folders. The
web folder contains the two JSP files and the deployment descriptors. The
src folder contains the source files for the servlet and Java bean classes.
Creating a Project
Creating a web project from the
provided source files
- Choose File > New Project (Ctrl-Shift-N). Under Categories, select Web.
Under Projects, select Web Project with Existing Sources. Click Next.
- In Location, click Browse to select the web application's document root. The
document root is $UNZIPHOME, the folder to which you
unzipped the ProfilingTutorial.zip file.
- In Project Name, type ProfilingTutorial. Click Next.
- Click Finish. The IDE creates the $UNZIPHOME/nbproject
project folder and the $UNZIPHOME/build.xml file.
The ProfilingTutorial project opens in the
IDE. You can view its logical structure in the Projects window and its file
structure in the Files window.
- This final step is only required when NetBeans is configured to use JDK v5 as
the default Java Platform.
- The current Profiler only supports .class files created by
JDK v1.4.2, so if you have not installed a v1.4.2 JDK and configured it as a NetBeans
Java Platform, you will need to do so. Note that in its beta release the NetBeans Profiler installs
a JDK based on v1.4.2 - you set it as JAVA_HOME up in the
Configuring Tomcat step. For more information refer to the online
Profiler help.
- In the Projects window right-click the ProfilingTutorial
entry and choose Properties. Select a Java Platform that uses the v.1.4.2 JDK and then
click the OK button.
- In the Tomcat bin folder, make a backup copy of catalina.50.bat (on
Windows) or catalina.50.sh (on Unix).
- Make the same edit to catalina.50.bat (on Windows) or catalina.50.sh (on Unix) that
you made in the
Configuring Tomcat step.
Running the Project
- In the Projects window right-click the ProfilingTutorial entry and choose
Clean and Build Project. Then right-click the ProfilingTutorial entry again
and choose Run Project. This will cause the IDE to build the project, start Tomcat, and then
display the index.jsp page in a browser window.
- Verify that Tomcat started correctly by clicking the Bundled Tomcat
tab in the IDE's Output window. Scroll to the top of the Tomcat output to verify
that Tomcat was started with the NetBeans Profiler JVM. Examine the line
that begins with Using JAVA_HOME; the Java home should be the folder
that contains the NetBeans Profiler JVM. If Tomcat does not start or the JAVA_HOME
is not the directory that contains the NetBeans Profiler JVM, then verify that you
followed the instructions in the Configuring Tomcat step.
Sample output for Windows is illustrated below.

- A browser window should have opened and displayed the
http://localhost:8084/ProfilingTutorial/ page. Verify that the web application is working by
typing NetBeans User into
the name field and clicking the OK button. The result should be similar to the
illustration below.

Monitoring Runtime Behavior
Attaching to a Running Application
Now that you have verified that Tomcat is using the JVM included with the NetBeans
Profiler you can attach the IDE's profiling tools to that JVM and monitor its runtime
behavior.
- Choose Profile > Attach Profiler. The Specify Attach Settings dialog is
displayed.
- For Attach To: choose J2EE Web/App Server
- For Running on: click the This Computer radio button
- For Attach Settings click the Dynamic Attachment radion button and then click
the Select Running VM radio button. Select
the Tomcat entry (typically org.apache.catalina.startup.Bootstrap start) from the list of
VMs.
- In Working Directory type the fully
qualified name of Tomcat's bin folder. As an example, a typical value on
a Windows system would be:
C:\Program Files\netbeans-4.0\nb4.0\jakarta-tomcat-5.0.28\bin
And on Unix the value will be something like:
/export/home/gs/tools/netbeans/40/nb4.0/jakarta-tomcat-5.0.28/bin
- Click the OK button. The Attach and Profile dialog is displayed.
- Click the large Monitor Application button.
Make sure that the Enable Threads
Monitoring option is not checked.
- Click the Attach button.
The NetBeans Profiler displays three graphs in the output window, as illustrated below.
The graph on the left is the easiest to understand. The red shading indicates the allocated
size of the JVM heap, updated approximately once per second. The purple
overlay indicates the amount of heap space actually in use. In the example above the
allocated heap size at the last update was almost 14 megabytes. Of that 14 megabytes
a little over 4 megabytes is actually being used to hold Java objects.
The graph on the right is also easy to understand. It merely shows the count of active
threads in the JVM, updated approximately once per second.
The graph in the center is the most interesting. It shows two important heap
statistics.
- The blue line is the percentage of execution time spent by
the JVM doing garbage collection and is graphed against the y-axis on the right
edge of the graph. Time spent by the JVM doing garbage collection is time that is
not available for it to run your application. So if the blue line indicates a large
percentage you may want to consider tuning the JVM by configuring a larger heap
size (refer to the -Xmx parameter
documentation)
or perhaps switching to a different garbage collection
algorithm.
-
The red line is surviving generations and is graphed against the y-axis scale
on the left edge of the graph. The count of surviving generations is the number of different
ages of all the Java objects on the JVM's heap, where "age" is defined as the number of
garbage collections that an object has survived. When the value for surviving generations is low it
indicates that most of the objects on the heap have been around about the same amount of time.
If, however, the value for surviving generations is increasing at a high rate over time then it
indicates your application is allocating new objects while maintaining references to many
of the older objects it already allocated. If those older objects are in fact no longer
needed then your application is wasting (or "leaking") memory.
Clicking the

button will
cause the IDE to display larger versions of the three graphs in the main display window.
Determining CPU Time Used by a Method
Switching to Performance Analysis Mode
The Profiler is attached to the Tomcat JVM, but is only monitoring high level statistics. To
find out detailed information about the performance of a specific method (or methods) in
the application you will need to modify the Profiler's settings.
- Click the
button or
choose Profile > Modify Profiling.
- Click the Analyze Performance button.
- Select the Part of Application radio button. Then click the
Select button that is next to the Part of Application radio button.
- Click the Add button.
- Click the Select button. The Profiler displays the Select Class tree.
- Expand the ProfilingTutorial entry by clicking its plus sign icon.
- Expand the Source Packages entry by clicking its plus sign icon.
- Expand the org.me.hello entry.
- Expand the RequestHandler.java entry.
- Click the RequestHandler entry and then click the OK button.
- The methods in the RequestHandler class are now displayed in the Select Methods dialog
as illustrated below. Click the processRequest method and then click the OK button.

- Select the processRequest method by clicking on it in the list of
Root Methods and then click the OK button.
You have just selected processRequest as the root method for performance analysis. This means
that the processRequest method and all methods that it calls, and all methods that they
in turn call (and so on) will be monitored. Starting
from processRequest, the
Profiler does analysis of the method call graph to determine which methods need profiling.
Only those methods are profiled - the rest of your application will continue to run at full
speed with no profiling overhead.
- Click the OK button on the Modify Profiling dialog.
Running the Profiled Method
Now that you have chosen processRequest as a root method you need to use the
portion of the web application that causes that root method to run. This is easy to do
because the processRequest method handles all requests from the index.jsp page.
- In your web browser click the Back button to return to the
http://localhost:8084/ProfilingTutorial/ page.
- Click the OK button to resubmit "NetBeans User" as your user name. It will take a bit
longer before the response appears because the Profiler is monitoring performance of the
processRequest method.
- After Hello, NetBeans User! displays in your browser, click the
button or
choose Profile > Get Current Results.
Interpreting the Performance Analysis Graphs
The Profiler displays the latest performance results, as illustrated below.
The top window shows the complete method call graph beginning with the root method.
The processRequest method ran for 168 milliseconds (ms). Note, however, that very
little time was spent running the instructions of the processRequest method itself -
the sixth line in the window shows the "self time" for processRequest to be only 0.421 ms.
The vast majority of the time was spent in methods called by processRequest. In particular,
the forward method took up 84.7% of the execution time. This is not surprising
given the amount of work the forward method has been given to do.
The power of the NetBeans Profiler is it helps you identify bottlenecks in your code
that were not expected or that will prevent your application from scaling well.
Note that the createUniqueID method took up 11.3% of the execution time. You can
click the plus sign next to the createUniqueID entry to investigate exactly where
the time went. If you
examine the source code for createUniqueID you will discover it uses a hideously
inefficient algorithm that should be redesigned.
The bottom window is a flatter depiction - it shows the "self time" for each
method in the call graph.
Monitoring the Creation of Objects
Switching to Memory Analysis Mode
The Profiler can do detailed analysis (also referred to as instrumentation) of CPU performance or memory
usage, but it cannot do both at the same time. To
find out detailed information about the allocation and garbage collection of
objects on the JVM's heap you will need to modify the Profiler's settings.
- Click the
button
or choose Profile > Modify Profiling.
- Click the Analyze Memory Usage button.
- Select the Record both object creation and garbage collection radio button.
- Click the OK button.
Running the Profiled Application
Now that you have chosen analyze memory usage you need to use the
web application in order to determine whether it is using memory efficiently.
- In your web browser click the Back button to return to the
http://localhost:8084/ProfilingTutorial/ page.
- Click the OK button to resubmit "NetBeans User" as your user name.
- After Hello, NetBeans User! displays in your browser, click the browser's Back button
to return to the previous page.
- Repeat steps 2 through 3 nine times. Repeated submission of the same user name is
necessary for this demonstration.
- Click the
button or
choose Profile > Get Current Results.
- The Profiler displays the latest memory analysis results in a table. Click
the Class Name column to sort the rows by class name.
- Scroll down through the table rows until the row for the
org.me.hello.NameHandler class is displayed.
Interpreting the Memory Analysis Graphs
The illustration below shows the statistics for the org.me.hello.NameHandler class.
The columns provide object allocation and memory usage information.
- Total alloc. obj. (on the far right) is easiest to understand. This is the total count
of all objects of this class that have been created. For the NameHandler class this value is
10, which is the number of times you pressed the Ok button on the web application's form.
- Allocated Objects is the number of objects that the Profiler is actually monitoring.
In this example, of the 10 instances of NameHandler that have been created
the Profiler is only monitoring 1 of those instances.
By default
this number will be approximately ten percent of the value of total allocated objects (so the
numbers you see might vary a bit from the illustration). By monitoring
only a subset of the created objects the Profiler is able to dramatically reduce the overhead
it places on the JVM, which then allows your application to run at close to full speed.
- Live Objects is the number of the Allocated Objects that are still on the JVM's heap and
are therefore taking up memory.
- The two Live Bytes columns show the amount of heap memory being used by the Live Objects.
One column displays a graph, the other displays text.
- The Age Average value is calculated using the Live Objects. The age of each object is the number
of garbage collections that it has survived. The sum of the ages divided by the number
of Live Objects is the Age Average.
- The Generations value is calculated using the Live Objects. As with Age Average, the
age of an object is the number of garbage collections it has survived. The Generations value
is the number of different ages for the Live Objects.
You can use this information to help track down memory leaks. The value for Generations
is the same as the Surviving Generations value described in the Interpreting the
Monitor Graphs section, but restricted to the objects of a single class. This finer granularity
of monitoring can help you find the specific objects that are wasting heap space.
In this example,
though, you do not even need Generations to see a problem with the NameHandler class. The Total
alloc. obj. value is 10. The intent of the servlet code was to reuse NameHandler objects
when the same user name is entered. Clearly, that is not happening. The bug is in the
processRequest method: the key used to check for an entry in the Map is not
the same as the key used to store the entry. The result is a pretty typical Java memory
leak: an object is placed into a Map and then forgotten.
Another handy tool for understanding application behavior is to see where in your code
the objects of a particular class are being allocated. This can often provide clues about
why an object is still on the heap. The NetBeans Profiler will display stack traces for any
class if you right-click the class's entry in the table and choose Show Allocations Stack Traces.
To end the profiling session, choose Profile > Detach.
Exploring Further
This tutorial has just scratched the surface of the Profiler's many powerful features.
Refer to the NetBeans Profiler help file for more information on these topics.
- When profiling CPU usage a class filter can be defined to prevent the profiling
of methods outside your application (for example all methods in java.*). This helps keep your application
running at closer to full speed.
- Profiling CPU usage can interfere with the JVM's bytecode optimizations, causing
the reported CPU times to not match real world performance. Techniques are available
though for minimizing the Profiler's affect.
- The Analyze Memory Usage feature can be limited to monitoring just object allocation.
This will decrease the Profiler's impact on performance.
- If when analyzing memory usage you discover that only a few classes seem to be
causing problems, you can disable the monitoring of objects of all other classes.
- Features are available that will monitor your application's startup time
or a specific code fragment in your application.
- Detailed thread statistics are available.
- Remote profiling - profile an application that is running on a different machine.