Profiling Tomcat Webapp with VisualVM and NetBeans – Pitfalls
Posted by Jakub Holý on February 25, 2012
Profiling a webapp running on Tomcat with VisualVM or NetBeans wasn’t as easy as expected, so this is a brief record of what to avoid to succeed.
Environment: Mac OS X, Java JDK 1.6.0_29, Netbeans 7.1, VisualVM 1.3.3 (installed separately), Tomcat 6.
- VisualVM Sampler and Profiler: To be able to drill down to the slow methods you need to take a snapshot before you stop the sampling/profiling (there is a [Snapshot] button above the Hot Spots list). This is not very intuitive and the interface doesn’t communicate it.
- VisualVM Profiler: Excludes Thread.sleep() & Object.wait() time (as opposed to the NetBeans profiler where you can choose to include/exclude them) => if you method is spending lot of time waiting for a lock, you won’t discover it
- You might need to allow unsafe, passwordless JMX connections in your Tomcat config, see Resources
- While VisualVM was able to dynamically connect to my Tomcat, NetBeans wasn’t able to do it and hasn’t provided any notification about the failure. The only visible manifestation was that it wasn’t showing and collecting any data. Solution: Use the “Direct” attach invocation, i.e. starting the target java application with the NetBeans profiling agentlib.
Extremely useful tool, included in JDK since 6.0 (command line: jvisualvm) or on the VisualVM page.
- Automatically discovers local Java processes and can connect to them (if they run Java 6+)
- Monitoring – threads, heap, permgen, CPU, classes
- Sampler – low-overhead profiling tool (takes thread snapshot at regular intervals and compares their stack traces to find out where most time is spent)
- Plugins, such as MBeans, Tracers
- Profiler – a simpler version of NetBeans profiler (comparison here); it can dynamically attach to running (Java 6+) processes and instrument classes on-the-fly. The not very visible checkbox Settings in the right-top corner can be used to set the classes to start profiling from (syntax: my.package.** to include subpackages or my.package.* or my.pkg.MyClass) and the packages not to / only to profile (syntax differs here: my.package.* to include subpackages or my.package. or my.pkg.).
Sorry, the comment form is closed at this time.