Showing posts with label VisualVM. Show all posts
Showing posts with label VisualVM. Show all posts

Thursday, April 1, 2010

Dynamic Java Log Levels with JMX/LoggingMXBean, JConsole, VisualVM, and Groovy

One of the most popular uses of JMX is to change the logging level of an executing Java application that utilizes Java's built-in logging (java.util.logging). This is made possible by the platform MBean server and the built-in LoggingMXBean. As an example of this, consider the simple Java class below.


The Java Application that Logs

FickleLogging.java

package dustin.examples;

import java.util.logging.Logger;
import static java.lang.System.out;

public class FickleLogging
{
private static Logger LOGGER = Logger.getLogger(FickleLogging.class.getCanonicalName());

public static void main(final String[] arguments)
{
for (int i=0; i < 500; i++)
{
try
{
LOGGER.info("Sleep: " + i);
Thread.sleep(5000);
}
catch (InterruptedException threadException)
{
LOGGER.severe("InterruptedException: " + threadException.toString());
}
}
}
}


The simple class above logs every five seconds at the INFO level. Because INFO-level logging is turned on by default, this simple application will log out the increments in each loop. JMX and the LoggingMXBean make it possible to change the logging level dynamically so that these info-level logs do not get written.


Adjusting the Logging Level via JConsole

The name of the logger in the above code is the class name or "dustin.examples.FickleLogging." If I don't realize this or remember it exactly, I can look it up because LoggingMXBean provides a getLoggerNames() method. This is shown in the next screen snapshot with JConsole.



One can click on "Values" field to have it expanded to see the available logger names. The next image shows this expanded view with the name of the logger from this simple application highlighted.



The highlighted logger name can be copied and pasted into the first String parameter field (p0) in JConsole for the setLoggerLevel method and the new level of logging can be placed in the second field (p1). This is demonstrated in the next screen snapshot.



Because the logging level of the regular logging updates in the simple example was at info level, setting the logging level to SEVERE means the logging in the running application stops. It only starts again if we set the logging level to INFO or more detailed level of logging. This is more dramatic in an actually running environment, but the next screen snapshot attempts to capture this by showing how the count in the log statements stops for a while and then starts up again.



The above image reflects the fact that I changed the log level via JConsole to SEVERE after the sixth logged message and then started it logging again by changing the level back to INFO in time for the tenth loop.

See Using JConsole to Monitor Applications for additional details on using JConsole to set the java.util.logging level of a Java application.


Adjusting the Logging Level via VisualVM

VisualVM is another graphical tool one can use to set the logging level of the simple application that I started this post with. Once the MBeans plug-in for VisualVM has been downloaded and installed (all easily done with its wizard), that tab can be used just like JConsole's MBeans tab was used above. The next two screen snapshots show use of the logger names attribute and the setLoggerNames operation. Note the similarities with JConsole.






Adjusting the Logging Level with Groovy Script

JConsole and VisualVM are easy-to-use graphical interfaces for interacting with a Java application's java.util.logging-based logging level. However, there are times when one would prefer to change the log level of a running application via a command-line script. I demonstrate this next with a Groovy script.

To make the Java application accessible via remote client, I run it with the three system properties com.sun.management.jmxremote.port, com.sun.management.jmxremote.authenticate=false, and
com.sun.management.jmxremote.ssl. These are set as shown in the next screen snapshot.



You may notice in the image above that there is a skipped output between 8 and 12 in the count. This is thanks to the running of a simple Groovy script that uses JMX and is shown next.


#!/usr/bin/env groovy
//
// setLogLevel.groovy
//
// This script allows one to control the logging level of a Java application
// using java.util.logging that exposes its LoggingMXBean for management.
// Java applications using java.util.Logging may provide easily controlled logging
// levels even from remote clients.
//
if (!args)
{
println "Usage: setLogLevel loggerName logLevel host port"
System.exit(-1)
}
import javax.management.JMX
import javax.management.ObjectName
import javax.management.remote.JMXConnectorFactory
import javax.management.remote.JMXServiceURL
import java.util.logging.LoggingMXBean
import java.util.logging.LogManager

def serverUrl = "service:jmx:rmi:///jndi/rmi://${args[2]}:${args[3]}/jmxrmi"
def server = JMXConnectorFactory.connect(new JMXServiceURL(serverUrl)).MBeanServerConnection
def mbeanName = new ObjectName(LogManager.LOGGING_MXBEAN_NAME)
LoggingMXBean mxbeanProxy =
JMX.newMXBeanProxy(server, mbeanName, LoggingMXBean.class);
mxbeanProxy.setLoggerLevel(args[0], args[1].toUpperCase())


I could have made this script more sophisticated with Groovy's built-in CLI support, but I use simply command-line args support here. The four necessary arguments after the script name are the Logger's name ("dustin.examples.FickleLogging"), the logging level to change to (such as SEVERE or INFO), the host of the application that's doing the logging ("localhost"), and the port via which JMX remote management is enabled (9999).

With the proper parameters passed to it, this Groovy script connects to the application started with remote JMX exposure and is able to adjust that application's logging level. More elaborate and sophisticated scripts could be written that could make it just a few keystrokes for a developer to quickly change the logging level of software as necessary.


Conclusion

Selecting the appropriate level of logging can be difficult both in terms of setting the level at which individual messages should be logged and in terms of what level of messages should actually be written out. The ability to adjust the level of logs that are written dynamically provides developers with more options in using logging for debugging and other purposes. In this post, I have attempted to demonstrate how easy it is to adjust the level at which logged messages are written by a particular Java application that logs with the built-in Java logging facilities. I have also demonstrated doing this with JConsole, VisualVM, and a Groovy script.

Monday, July 6, 2009

2009 JavaOne: VisualVM

VisualVM

I have been excited about the inclusion of VisualVM with Sun's HotSpot since its bundling with Java SE 6 Update 7. VisualVM combines the best of several other Sun-provided Java tools such as the visual tool JConsole and command line tools such as jinfo, jmap, jstat, and jstack. VisualVM can also be downloaded separately from Sun's Java SE 6 implementation from https://visualvm.dev.java.net/download.html.


VisualVM at 2009 JavaOne

I have spoken with many experienced Java developers who have been unaware of the existence of VisualVM. I also found it interesting that in the recent VisualVM blogging contest, VisualVM was described as "the best kept secret" in Java development. Besides holding the blogging contest related to VisualVM, other measures have been taken to make sure that the secret is out. In this blog post, I will focus on two presentations from 2009 JavaOne that go a long way toward getting the word out about the existence and benefits of VisualVM: "Monitoring and Troubleshooting Java Platform Applications with JDK Software" (BOF-4724) and "Hop on Board the Java Troubleshooting Platform" (TS-4247).


Monitoring and Troubleshooting Java Platform Applications with JDK Software

The Birds of a Feather session "Monitoring and Troubleshooting Java Platform Applications with JDK Software" was led by Mandy Chung and Tomas Hurka. Each of these Sun employees possesses the credentials to conduct such a BOF session.

Mandy Chung has worked with JConsole and various Java management related APIs. Her blog post Java SE 6 Monitoring, Management, Diagnosability may be the best online starting point for learning about Java SE 6 management, monitoring, and diagnostics. That particular blog post lists Java SE 6's many features and tools with a concise description of each and links to additional resources on that feature. Chung is also the author of Monitoring and Managing Java SE 6 Platform Applications and a contributor to the Troubleshooting Guide for Java SE 6 with HotSpotVM.

Tomas Hurka presented a BOF at 2008 JavaOne that introduced VisualVM and was called "VisualVM: Integrated and Extensible Troubleshooting Tool for the Java Platform" (BOF-5223). Perhaps most importantly in terms of credentials, Hurka is the lead developer on the VisualVM project.

The BOF presentation only has 17 slides (probably due to demonstrations and discussion), but these are 17 content-packed slides. One of my favorite slides in this presentation is the third slide of the presentation. It is called "Monitoring and Troubleshooting Tools" and contains a table that maps a management/monitoring/troubleshooting feature to a Sun-provided command-line (CLI) tool and to the relevant graphical (GUI) tool. Many articles and blog posts and even the VisualVM home page talk about VisualVM being a composite of the various command-line tools. The table of this slide does the best job I have seen of tying command-line tools to VisualVM and associating VisualVM with the specific troubleshooting feature provided by the command-line tool.

The majority of the presentation focuses on providing additional details and usage information regarding the command line tools and graphical tools mapped on the slide just mentioned. In particular, focus is placed on JConsole, VisualVM, diagnosing deadlocks, diagnosing memory leaks, diagnosing hot lock contention, diagnosing OutOfMemoryError, diagnosing a hung process on Linux or Solaris (Windows support planned), and diagnosing a few other negative conditions.



Hop on Board the Java Troubleshooting Platform

A Sun employee and member of the NetBeans Team, Geertjan Wielenga focuses in this presentation specifically on VisualVM. Wielenga may be best known to many developers for his DZone/JavaLobby articles on NetBeans and VisualVM. The presentation can be roughly described as made up of two major pieces. The first half is devoted to introductory and overview information on using VisualVM and the second half is dedicated to extending VisualVM.

These slides provide a useful introduction to VisualVM, what it is, and why and how one might use it. The slides also show how and why VisualVM can be extended. Two of my favorite slides in this presentation appear toward the end. The slide called "The Future" focuses on potential improvements to VisualVM such as OSGi support and the possibility of more plug-ins for VisualVM. The "References" slide provides links to several useful resources on VisualVM. There is a relatively large amount of demonstration code included with the slides that helps understand lower level details.


Conclusion

The two presentations briefly reviewed here contribute to getting the word out about VisualVM. I have blogged on VisualVM several times and cannot say enough good things about the tool.


Additional Resources

VisualVM Project Page

JavaLobby VisualVM Tagged Articles

The Best Kept Secret in the JDK: VisualVM

VisualVM: Free and Open Source Java Troubleshooter

Java VisualVM Tech Notes

Thread Analysis with VisualVM

Heap Dump and Analysis with VisualVM

Acquiring JVM Runtime Information

VisualVM: jinfo and So Much More

From JConsole to VisualVM

Wednesday, June 24, 2009

Thread Analysis with VisualVM

Although jstack (Java Stack Trace) is a useful tool for learning more about a how a Java thread is behaving, VisualVM is an even easier method for obtaining the same type of information.

It is easy to run jstack as demonstrated in the next screen snapshot:



Only the top portion of the generated stack trace information is shown above. The output of an entire jstack run looks similar to that which follows:


2009-06-24 23:25:26
Full thread dump Java HotSpot(TM) Client VM (14.0-b16 mixed mode, sharing):

"RMI Scheduler(0)" daemon prio=6 tid=0x04bb4c00 nid=0x126c waiting on condition [0x048ef000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x2492dac8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1925)
at java.util.concurrent.DelayQueue.take(DelayQueue.java:160)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:583)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:576)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)

Locked ownable synchronizers:
- None

"RMI TCP Accept-0" daemon prio=6 tid=0x023bfc00 nid=0xa74 runnable [0x0483f000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:390)
- locked <0x2492dc48> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:453)
at java.net.ServerSocket.accept(ServerSocket.java:421)
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:34)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:369)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:341)
at java.lang.Thread.run(Thread.java:619)

Locked ownable synchronizers:
- None

"Low Memory Detector" daemon prio=6 tid=0x02348000 nid=0xec4 runnable [0x00000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"CompilerThread0" daemon prio=10 tid=0x02343000 nid=0x108 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Attach Listener" daemon prio=10 tid=0x02342800 nid=0xf6c waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Signal Dispatcher" daemon prio=10 tid=0x02339c00 nid=0xac runnable [0x00000000]
java.lang.Thread.State: RUNNABLE

Locked ownable synchronizers:
- None

"Finalizer" daemon prio=8 tid=0x022f4000 nid=0xd14 in Object.wait() [0x044cf000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x248ee9a0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
- locked <0x248ee9a0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

Locked ownable synchronizers:
- None

"Reference Handler" daemon prio=10 tid=0x022f2c00 nid=0x1198 in Object.wait() [0x0240f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x248eea28> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
- locked <0x248eea28> (a java.lang.ref.Reference$Lock)

Locked ownable synchronizers:
- None

"main" prio=6 tid=0x00209000 nid=0x1134 runnable [0x002af000]
java.lang.Thread.State: RUNNABLE
at java.util.Arrays.copyOf(Arrays.java:2882)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:390)
at java.lang.StringBuilder.append(StringBuilder.java:119)
at dustin.examples.tools.AnalyzableImpl.loopProvidedNumberOfTimes(AnalyzableImpl.java:48)
at dustin.examples.tools.AnalyzableImpl.main(AnalyzableImpl.java:80)

Locked ownable synchronizers:
- None

"VM Thread" prio=10 tid=0x022f1400 nid=0x10c runnable

"VM Periodic Task Thread" prio=10 tid=0x02348c00 nid=0x278 waiting on condition

JNI global references: 872



VisualVM makes it easy to monitor application threads. VisualVM offers the capability to generate and view the jstack-generated stack trace. The first way to do this is to right-click on the appropriate Java process and select the option "Thread Dump." This will generate a thread dump file whose name appears under the selected Java process as shown in the following screen snapshot.



A second way to get the thread dump generated in VisualVM is to use the "Threads" tab and click on the button "Thread Dump." This button is demonstrated in the next screen snapshot.



Whether the right-click option is used or the "Thread Dump" button is pressed, VisualVM generates jstack thread dump output file and displays it as shown in the next screen snapshot.



As discussed and demonstrated, VisualVM allows for easy generation of a stack trace dump with jstack. However, VisualVM provides much more than that for thread analysis.

The screen snapshot above that showed the "Thread Dump" button also conveniently demonstrates VisualVM's Timeline tab that demonstrates in a live fashion the "live" threads. These colored horizontal bars represent individual threads. Their display is enabled because the "Threads visualization" checkbox is checked.

Another useful tab on VisualVM is the "Threads" "Table" view that provides textual overview information on the threads. This is demonstrated in the next screen snapshot.



Any individual thread can be clicked on to see the detailed Threads view. This view, also under the "Threads" tab in VisualVM. When "Threads visualization" is checked, a pie chart is included that graphically indicates what each thread is doing. This is demonstrated in the next screen snapshot.




Conclusion

The jstack tool is a useful command-line tool, but VisualVM provides the same capabilities along with a significantly improved presentation and details.

Heap Dump and Analysis with VisualVM

In previous blog posts, I have covered using VisualVM to acquire HotSpot JVM runtime information in a manner similar to jinfo and how to use VisualVM in conjunction with JMX and MBeans in a manner similar to JConsole. This blog posting looks at how VisualVM can be used to generate and analyze a heap dump in a manner similar to that done with command-line tools jmap and jhat.

The jmap (Java Memory Map) tool is one of several ways that a Java heap dump can be generated. The Java Heap Analysis Tool (jhat) TechNotes/man page lists four methods for generating a heap dump that can be analyzed by jhat. The four listed methods for generating a heap dump are the use of jmap, JConsole (Java Monitoring and Management Console), HPROF, and when an OutOfMemoryError occurs when the -XX:+HeapDumpOnOutOfMemoryError VM option has been specified. A fifth approach that is not listed, but is easy to use, is Java VisualVM. (By the way, another method is use of the MXBean called HotSpotDiagnosticMXBean and its dumpHeap(String,Boolean) method.)

The jmap tool is simple to use from the command line to produce a heap dump. It can be used against a running Java process whose piocess ID (pid) is known (available via jps) or against a core file. In this post, I'll focus on using jmap with a running process's ID.

The jmap page states that jmap is an experimental tool with relatively limited capabilities on Windows that may not be available with future versions of the JDK. This page also lists options available to specify how jmap should generate a heap dump.

The following screen snapshot shows how jmap can be used to dump a heap.



The generated dump file, dustin.bin in this case, is binary as shown in the next screen snapshot.



The binary heap dump can be read with the jhat tool. Sun's Java SE 6 included implementation of jhat replaces HAT, which was formerly available as a separate download. It is almost trivial to run jhat. One need only invoke jhat on the heap dump file generated with jmap (or alternative dump generation technique) as shown in the next screen snapshot.



With the heap dump generated (jmap) and the jhat tool invoked, the dump can be analyzed with a web browser. The output on the console tells us that the dump is available on port 7000 (this default port can be overridden with the -port option). When I run the browser on the same machine on which I ran jhat, I can use localhost for the host portion of the URL. The starting page using localhost and port 7000 is shown in the next screen snapshot.



Arbitrary Object Query Language (OQL) statements can be written to find necessary details in the heap dump. The jhat-started web server includes OQL help at the URL http://localhost:7000/oqlhelp/. See also Querying Java Heap with OQL for more details on how to use OQL. However, one can often find what one needs simply using the already provided information and moving between pieces of information using the provided hyperlinks.

The following screen snapshot demonstrates one of the more useful pages available thanks to jhat's web server-based output of the heap dump. This page shows the number of instances of various Java objects, including platform objects.



A significant aid in understanding what these web pages generated by jhat mean is the VM Specification on Class File Format. In Section 4.3.2 ("Field Descriptors") of this document, there is a table that shows the mapping of field descriptor characters to the data type we use. According to this table, "B" indicates a byte, "C" indicates a char, "D" indicates a double, "F" indicates a float, "I" indicates an integer, "J" indicates a long, "L<someClassName>" indicates a reference (instance of a class), "Z" indicates a boolean, and [ indicates an array.

So far, I have looked at using jmap and jhat from the command-line to generate a heap dump and provide a web browser-based method for analyzing the generated heap dump. Although these tools are relatively easy to use, VisualVM provides similar functionality in an even easier approach.

One method for generating a heap dump in Visual VM is to simply right click on the desired process and select "Heap Dump". This method is shown in the next screen snapshot.



This generates the heap dump as indicated by its name underneath the Java process.



A second approach for generating a heap dump with VisualVM is to click on the Java process of interest so that relevant tabs ("Overview", "Monitor", "Threads", and "Profiler") come up in VisualVM. Selecting the "Monitor" tab provides the "Heap Dump" button as shown in the next screen snapshot.



Clicking on the "Heap Dump" button leads to a heap dump being generated just as it was with the right click option described above. This is shown in the next screen snapshot, which happens in this case to show the "Summary" tab of the analyzed heap dump.



In addition to the "Summary" tab of the heap dump analysis, other interesting details from the heap dump are presented in the "Class" tab. This tab includes horizontal bar charts that graphically indicate the percentage of total instances that are associated with each class. An example is shown in the next screen snapshot.



The displayed classes are spelled out rather than using symbols like those described above for jhat-based heap dump analysis. One can right-click on any class in the "Classes" tab and select "Show in Instances View" to see details on each individual instance of the selected class. This is shown in the next screen snapshot.




Conclusion

VisualVM provides several advantages when creating and analyzing heap dumps. First, everything from creation to analysis is in one place. Second, the data is provided in what may be considered a more presentable format with graphical support. Finally, other tools can also be used in VisualVM in conjunction with the heap dump analysis. VisualVM provides one-stop shopping for many of the development, debugging, and performance analysis needs of the Java developer.


Additional References

Troubleshooting Java SE

Troubleshooting Guide for Java SE 6 with HotSpot JVM (PDF)

Java SE 6 Performance White Paper

What's in My Java Heap?

Analyzing Java Heaps with jmap and jhat

Java Memory Profiling with jmap and jhat

Monday, June 8, 2009

Acquiring JVM Runtime Information

I have found the tools and utilities that come with the Sun-provided Java SDK (especially the monitoring and management tools) to be very useful in daily Java development. I have previously blogged on the use of several of these handy tools such as jps, JConsole, and VisualVM. Although my previous blog posts have generally focused on using a single particular tool to accomplish something, I am using this posting to look at how to acquire JVM runtime information using several different tools.

There are many reasons one might desire JVM runtime information. These include the ability to figure out why an application runs differently in two different environments, the ability to use other tools and utilities based on runtime information (such as Java process ID), and the ability to identify Java processes that are not closing even when politely asked.

jps

The jps command (Java Virtual Machine Process Status Tool) is one of the tools I use most often in my Java development. I have covered it more thoroughly before, but I quickly describe it here for convenience. The jps command options I generally use are "l" and "m." The overall command, jps -lm provides the process IDs of all running Java processes on that machine and the options provide enough detail to know which IDs go with which process descriptions. There are some permissions issues that can potentially reduce the usefulness of jps and the jps man page warns that "this utility is unsupported and may not be available in future versions of the JDK," but I have found this simple command-line tool to be enormously helpful.

jinfo

One of the ways to run the jinfo (Java Configuration Info) tool is run it against a Java process. The jps tool just mentioned can be used to retrieve the appropriate Java process ID.

The -help flag can be used to see how to use jinfo. There are fewer options available on Windows than on Linux. The options available to jinfo on Windows are shown in the next screen snapshot.



Even with the Windows jinfo, I can view individual Virtual Machine (VM) options. This is demonstrated in the next screen snapshot.



How do you know which VM options are available? In Windows, jinfo does NOT support the -flags option which is supposed to provide a list of VM options. However, the HotSpot VM options are available at http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp and Troubleshooting Guide for Java SE 6 with HotSpot VM also contains several of them. This limited version of jinfo for Windows has only been available since J2SE 6.

On Linux, the -flags option is supported and can be used to see all flags associated with the given Java process. The Linux version of jinfo also supports the -sysprops to view the system properties associated with the particular application and supports no option to see properties and command-line flags. The Linux version of jinfo is obviously more powerful than the Windows version.


JConsole

Command-line tools like jps and jinfo have several advantages such as reduced overhead, potentially faster performance, and availability to be used in non-interactive scripts. However, there are also situations when a graphical interface is preferred for ease of use or for improved presentation. JConsole supports visual representation of virtual machine information and has been available as a standard part of the Sun-provided JDK since J2SE 5 (and was improved for Java SE 6).

JConsole is particularly easy to use with Java SE 6 because the Attach API enables JConsole to automatically look up Java processes running on the same host and under the same user without any special properties being specified for the Java application being monitored (can be done with J2SE 5 if appropriate system properties are first specified). This automatic detection of local processes in Java SE 6 is shown in the next screen snapshot.



As the screen snapshot above indicates, it is easy to identify Java process IDs in JConsole as they are explicitly shown ("PID" column) in the first screen. When one clicks on one of these processes, the "Connect" button is enabled. When that button is clicked on, JConsole connects to the selected Java process.

Once JConsole connects to a selected Java process, six tabs are present by default (and JConsole allows creation of additional custom tabs). The "VM Summary" tab is useful for getting highly descriptive summary of characteristics and settings of the JVM. An example of this is shown in the next screen snapshot.



There is significantly more that can be gleaned from JConsole, but for now I'll focus on how to obtain the type of information provided by jinfo. The VM options can be obtained via the MXBean provided with the Sun implementation of Java called com.sun.management.HotSpotDiagnostic. The getVM operation on this MXBean allows the name of the desired VM option to be specified in a text field and that option's value is returned when the "getVMOption" button next to the text field is clicked. The next screen snapshot demonstrates this (note that this all takes place in the "MBeans" tab).



JConsole allows system properties to be accessed via its "MBeans" tab as well. They are accessed via the MXBean java.lang.Runtime. The next screen snapshot demonstrates how this appears when this MXBean is selected.



The only problem at this point is that the value javax.management.openmbean.TabularDataSupport is not exactly the type of thing we're looking for when we want to see system properties. Fortunately, one can simply click on this bold string and the entire area expands as shown in the next screen snapshot.



As the last screen snapshot demonstrates, one system property is shown at a time. The "Tabular Navigation" buttons with < and > icons can be used to move through the various properties. In this case, the displayed java.endorsed.dirs property is the 9th of 53 properties.

Besides being more aesthetically pleasing, JConsole offers the advantage of working well and fully on Windows as well as on Linux. The fact that JConsole is constructed to generically handle exposed JMX MBeans makes its use virtually limitless. Not only can it be used to monitor and management standard properties provided with the JVM, but it can even be used to manage and monitor custom JMX-enabled applications.


VisualVM

VisualVM has been available as a distinct open source product for some time, but has been included with Sun's JDK since Java SE 6 Update 7. It provides advantages of JConsole such as visualization of memory and performance data and generic access to JMX MBeans.

Like jconsole used to run JConsole, the jvisualvm command for running VisualVM is located in the same directory as the other Sun-provided Java tools such as java, javac, jps, and jinfo. Although I have discussed jinfo and VisualVM together before, I look at them together again here for convenience.

The next screen snapshot shows the VisualVM startup screen. Like JConsole, local Java processes running under the same user are automatically displayed with the Process ID in parentheses.



Clicking on the desired process leads to several tabs being shown. The "Overview" tab is shown in the next screen snapshot.



In the bottom right corner, there is a pair of tabs nested within this "Overview" tab. In the screen snapshot above, the "System Properties" tab is selected. As shown, all the properties are shown at once and a scroll bar on the right can be used to scroll down the list. The other nested tab can be used to see any VM arguments.

To see VM options, one can use the JMX-exposed MXBean used with JConsole. To access MBeans from VisualVM, the "MBeans" plugin should be installed as I have blogged about previously. Once the plug-in is installed, the "MBeans" tab can be accessed and used in a manner very similar to how the "MBeans" tab is used in JConsole. The next screen snapshot shows viewing of one of eight VM options this way.



Like JConsole, there is much more to VisualVM than is shown here. However, as these simple examples have shown, a wide variety of information about the JVM is available via VisualVM and JMX-exposed applications can be accessed generically from this tool.


Other Tools

Because the Sun JVM is widely instrumented to support monitoring and management via JMX, any JMX client (generic or custom) can be used to monitor and manage the JVM. However, I see very little reason to use other tools for JMX-based JVM monitoring and management with the ready availability of JConsole and VisualVM. For even more sophisticated non-Java client access of JVM information, compatible web services clients (implement WS-Management, such as winrm) can manage and monitor JVMs via the JMX Web Services connector.


Conclusion

There are many alternatives available for acquiring information related to the Sun JVM. These options get better and more prevalent with each new major Java release. This blog posting has attempted to demonstrate how the command-line tools jinfo and jps and the graphical tools jconsole and jvisualvm are readily available and easily provide information on the JVM.

Thursday, April 30, 2009

VisualVM: JRuby and the Ruby to JVM Spectrum

As I have worked with JRuby, it has been interesting to observe the intersection of the Java and Ruby communities. Because JRuby potentially combines with best of the JVM with the best of Ruby, it is perhaps not surprising that JRuby leads to a greater intersection of the Java community and the Ruby community. For example, because I have been working primarily in Java in recent months, I probably would not have been aware of the major controversy in the Ruby community surrounding a single presentation given recently at the Golden Gate Ruby Conference (GoGaRuCo).

Many Rubyists like to focus on the Ruby advantages that JRuby brings to Java, but there is no denying that JRuby also brings advantages of the JVM to Ruby. One particular area of interest here is the impact of the JVM on JRuby performance. In How JRuby makes Ruby Fast, Charles Nutter demonstrates how JRuby's performance improves as more JVM features (server mode, JIT compiling, and so forth) are employed. Some strict Ruby compliance must be sacrificed for some of the performance improvements, but this flexibility to selectively choose between the best features of Ruby and the JVM is one of the endearing features of JRuby.

As described in the JRubyWiki topic Performance Tuning, JRuby performance can be tweaked with JVM arguments and properties. Although these properties and JVM arguments can be set on the command-line, there are times you may want to know which ones are being used or what the default settings are. This is where VisualVM makes things really easy.

VisualVM is included with recent versions of Sun's implementation Java SE 6. It in many ways serves as a replacement for JConsole and a host of command-line tools provided with Sun's SDK. In his post Can Your Ruby Do This?, Ola Bini points out how JRuby is able to take advantage of the built-in JMX support in Java SE 6 for automatic detection, monitoring, and management. Similarly, VisualVM can be used to monitor JRuby processes by virtue of them running in the JVM.

To demonstrate this, I'll use VisualVM to monitor the running JIRB (JRuby's Interactive Ruby) tool. With jirb started on my local machine (it could also be accessed remotely, but local is slightly easier), I see the running process when I start Visual VM (jvisualvm at the command line) as shown in the next screen snapshot.



In this case, the only other Java process running on my local machine is VisualVM itself. This also provides evidence that JIRB does indeed run as a Java process (using class org.jruby.Main). When I click on the JRuby process, I can see the JVM arguments used in conjunction with running jirb as shown next.



Because I had downloaded and installed the JConsole-like MBeans plug-in for VisualVM earlier, the JMX-exposed MBeans for JIRB are available. These are shown in the next screen snapshot in the MBeans tab (this tab is not available in VisualVM until it is explicitly downloaded and installed using Tools-->Plugins).



As the last image indicates, the JRuby process exposes a long list of configuration items for viewing. This allows VisualVM, JConsole, or any other JMX-enabled client to see how the JRuby runtime is configured in that particular case.

JRuby brings together the Java world and the Ruby world both in technical aspects and in people/community/political aspects.

Saturday, November 22, 2008

VisualVM: jinfo and So Much More

The 16 November 2008 edition of the JavaTools Community Newsletter includes a Tools Tip regarding the jinfo command-line tool provided with Sun's JDK. The same tool tip also points out that jps can be used to identify the identifiers of the Java processes. The command-line tools such as jinfo are useful and it is nice to see quick tips like this one that remind us of their existence (or point out their existence).

The jinfo tool does have disadvantages for some situations. For example, it is not supported in Windows for J2SE 5 and only supports limited functionality in Java SE 6 on Windows. The Diagnostics Tools and Options section of the Troubleshooting Guide for Java SE 6 with HotSpot VM document also points out that jinfo is experimental (subject to change or not even be available in future versions of Sun's Java implementation). See jinfo's Detailed Tool Description for a very clear single-sentence description of the significantly broader jinfo support available in Linux and Solaris OS than the very limited Windows jinfo support.

A final disadvantage of jinfo is its command-line nature. While there are cases where this is advantageous, some people prefer a graphical interface. Finally, another disadvantage of jinfo and the other highly useful command-line tools provided with Sun's JDK is that they are separate tools. It would be nice to have all these tools in one place. That's where VisualVM comes in.

The functionality of jinfo along with several other similar command-line tools and JConsole is now available in the implementation of VisualVM included with the Sun JDK since Java SE 6 Update 7.

One of the nice features of jinfo is the ability to see what System properties are in play for a given Java application. The next three screen snapshots demonstrate how easy it is to see this information with VisualVM (started by running jvisualvm). After that, I'll show an even easier way to see System Properties and JVM Arguments with VisualVM.


Selecting Application and Heap Dump from VisualVM

The first image demonstrates that a Java application (in this case VisualVM itself) needs to be selected and then that application needs to be right-clicked on to select and see the Heap Dump tab (the second screen snapshot).




VisualVM Heap Dump Tab

This screen snapshot demonstrates the Heap Dump tab. There is a link to click on to see System Properties. The next screen snapshot demonstrates a piece of the tab when the System Properties has been selected.




System Properties Displayed in VisualVM




System Properties Via VisualVM Overview

It turns out that it is even easier to see the System Properties with VisualVM than with the Heap Dump process described above. As the next screen snapshot indicates, one can simply use the "Overview" tab after clicking on a particular Java process. The "System properties" sub-tab can be selected to see the system properties.




JVM Arguments

VisualVM also makes it easy to see JVM arguments. The same "Overview" tab in VisualVM just shown has sub-tab for "JVM arguments." When selected, the JVM arguments are shown as depicted in the next screen snapshot.



The previous screen snapshot demonstrates that VisualVM provides the JVM arguments via its "Overview" tab. This same information can also be seen in JConsole in its "VM Summary" tab.


Conclusion

The command-line tools provided with the Sun JDK are very useful. VisualVM offers many of the benefits of these tools with features of its own. In this particular example, VisualVM makes it really easy to access the same type of data that jinfo provides and in addition works well on Windows operating systems. In fact, all of the screen snapshots in this blog entry were taken from VisualVM running on Windows.

Thursday, August 28, 2008

From JConsole to VisualVM

With the release of VisualVM as a standard part of Sun's JDK distribution since JDK 6 Update 7, it is likely that Java developers will begin using VisualVM in situations in which they previously used the separate tools such as jinfo, jmap, jstack, jstat, and JConsole. Fortunately, two of the main features JMX developers were likely to use in JConsole can be used with VisualVM as well.

One feature I use very often in JConsole is the "MBeans" tab for displaying manageable and monitorable attributes, operations, and notifications related to my custom MBeans. While this tab does not exist in VisualVM when it is first run from the command-line in Java SE 6, it is trivial to add the MBeans plugin to get behavior very similar to that provided in JConsole.

To run VisualVM provided with the JDK distribution, use the command jvisualvm from the command prompt. This is demonstrated in the following screen snapshot:



When first started up, VisualVM does not have an MBeans tab like that used in JConsole. However, one can easily add the MBeans plugin by selecting Tools->Plugins from VisualVM. The following screen snapshots show how to do this.

This first screen snapshot shows selection of Tools->Plugins.



The next screen snapshot shows the MBean tab selection from among the available VisualVM plugins.




The next screen snapshot demonstrates what the MBeans tab looks like in VisualVM.



The MBeans tab in VisualVM is very familiar to anyone who has used the MBeans tab in JConsole.


Another useful JConsole feature is the ability to add custom tabs to JConsole. While the VisualVM JConsole Plug-in Wrapper Tab document recommends using VisualVM's own customizability features when developing new support for VisualVM, it can be handy to use existing JConsole plug-ins with VisualVM. The just-referenced document VisualVM JConsole Plug-in Wrapper Tab does a nice job of covering how to use a custom JConsole plug-in tab in VisualVM. That example uses the JDK-provided JTop custom plugin for the example.

The three screen snapshots that follow show how easy it is to install the JConsole plugins tab wrapper in VisualVM and to select a JConsole plugin for use in VisualVM. The final image shows how one JConsole plugin, the JTop plugin provided with the SDK, appears in VisualVM.

This first image shows the details related to the JConsole plugin tab wrapper.



The next image shows selection of a particular JConsole tab plugin once the wrapper plug-in for VisualVM has been installed.



This final image demonstrates what the JTop JConsole tab looks like in VisualVM via VisualVM's JConsole plug-in tab wrapper.




For individuals and organizations with large investments in JConsole custom tabs, the VisualVM wrapper plug-in allows those plug-ins to be leveraged in VirtualVM without massive re-writes. For those who appreciate JConsole as an easy-to-use client of custom JMX applications, VisualVM can provide similar capabilities via its MBeans plugin. Besides providing many of the advantages of JConsole via plug-ins and out-of-the-box support, VisualVM provides graphical representation of the monitoring data provided by many tools other than JConsole. With the JConsole-friendly plug-ins mentioned in this blog entry in use, VisualVM is able to combine the strengths of JConsole with the value found in other Sun JDK-provided management and monitoring tools.