Unable to use JVisualVM profiling for Tomcat7 running as a service on Windows7

Mr Anderson picture Mr Anderson · Jan 29, 2013 · Viewed 8.8k times · Source

I'm trying to profile a Servlet running in Apache Tomcat (7.0.34) as a service on Windows 7 (64 bit) using JVisualVM (JDK 1.7.0 - 06, 64 bit) running locally.

Initially I had the problem of Tomcat not showing in the list of local applications due to the differing "java.io.tmp" property bug/feature, but worked around it as advised in several posts in this forum.

However although the Tomcat process now shows in the list of local applications as "Local Application", when I open the process there are no tabs for Monitor, Threads, Sampler or Profile - only the Overview tab for which the JVM arguments and Sytem Properties sub-tabs show the dreaded "not supported for this jvm" message.

I have double checked the following items:

  • that both Tomcat and JVisualVM are running the same version of Java by looking at the JVM properties in JVisualVM (using a JMX connection for Tomcat)
  • that both Tomcat and JVisualVM have the same "java.io.tmp" path by looking at the System Properties in JVisualVM (again using a JMX connection for Tomcat) AND looking at the actual TMP/TEMP directory and confirming that the PID files for both exist
  • that the file system is NTFS
  • that the Windows user does not have an underscore in the name (Note: the user does have a period in the name as we are using network logins of the form "firstname.lastname", however I have no problems viewing other Java applications in JVisualVM so don't think this is an issue)
  • that both Tomcat and JVisualVM are being executed as the same Windows user by looking at the processes in Task Manager

A couple of final points:

  • I need to Profile the Servlet so using JMX is not sufficient
  • I was able to profile on a Windows XP machine (Java 7, Tomcat 7 as a service), so would appear to be a Windows 7 / 64 bit thing?

If anyone has had and solved this issue obviously the solution would be much appreciated. However would be useful to just know if other people are running the same configuration - Windows 7 64 bit, Java 7 64 bit, Tomcat 7 running as a service - successfully.

Update: Instead of running as a service, I ran Tomcat using the batch file and all worked perfectly: what is it about running as a service?

Answer

Christian K. picture Christian K. · Jan 27, 2014

As already hinted in my previous comment. I guess the simple answer is it's not possible. In order to realize the communication between jconsole/jvisualvm and the to be monitored process Java uses memory mapped files. In the end it boils down to a certain Windows API call that fails due to the "Windows Service Hardening" [1] feature added in Windows Vista and which, of course, also exists in Windows 7 and later versions.

The call which fails is to the function OpenFileMapping as can be seen in perfMemory_windows.cpp line 1402 [2]. During my experiments the method is called with an argument of the form "hsperfdata_[username]_[process id]". As further detailed in Microsofts explanation of the differences introduced by the service hardening (see [3]) communication won't work if no name prefix is used: "If a user application [...] synchronizes with the service by creating or opening objects with the Local\ prefix (or no prefix, which defaults to Local), the application no longer works as expected."

If someone wants to take a look himself. You can use the Logger tool [4] included with the Windows debugging tools to trace API calls.

Also the Sysinternals Process Explorer is very handy as it shows the full names used for memory mapped files via its "Find Handle or DLL..." function. Just search for handles containing "hsperf".

As a side note: The workaround to delete or otherwise mess with the temporary directory which contains the hsperf data boils down to the fact that the case of the username used by the to be monitored process and the monitoring process need to be consistent. But instead of changing the temporary directory you can also easily change the USERNAME environment variable used by the monitoring process. You can also see how it is being used in in perfMemory_windows.cpp line 272 [2].

[1] http://technet.microsoft.com/en-us/library/cc507844.aspx#EHF

[2] http://hg.openjdk.java.net/jdk7/hotspot-rt/hotspot/file/5dce25362b8a/src/os/windows/vm/perfMemory_windows.cpp

[3] http://msdn.microsoft.com/en-us/windows/hardware/gg463353.aspx

[4] http://msdn.microsoft.com/en-us/library/windows/hardware/ff560123(v=vs.85).aspx