Monitoring WildFly using VisualVM

In this updated tutorial we will learn how to connect the latest version of WildFly application server using VisualVM monitoring tool.

VisualVM is a free tool to monitor and profile Java application. In the past, VisualVM used to be shipped with Oracle JDK 6~8 as Java VisualVM. It has been discontinued in Oracle JDK 9. Today, VisualVM is distributed as a standalone tool and bundled with the GraalVM. Both are the same bits with the same features. Standalone tool runs on any compatible JDK, bundled tool is configured to run using the host GraalVM.

If you opt to download VisualVM as standalone application, you can grab a copy of it from here: https://visualvm.github.io/download.html

Then, unzip the downloaded archive. The archive already contains the top-level visualvm directory. Start VisualVM by invoking the binary appropriate for your OS, which is located in the bin folder:

$ ./visualvm

The following sections provide instructions for using VisualVM to connect to a local or remote WildFly JVM. As for JConsole, we will at first check out how to connect to a local JVM process and then to a remote server.

Connecting to a Local WildFly JVM Using VisualVM

Before we start WildFly, we need to add to WildFly modules the JFluid Server API which allows starting the full instrumentation profiling, calls to which are injected into the target application bytecodes when they are instrumented.

The required library, named jfluid-server-15.jar, is included into VisualVM distribution in the directory path $VISUALVM_HOME/visualvm/lib/

First, we need to make the JFluid API available as System Packages. This requires to include its top packages in the JBOSS_MODULES_SYSTEM_PKGS environment variable. For standalone servers, open the file standalone.conf and add the package ‘org.graalvm.visualvm’ right after byteman’s packages:

if [ "x$JBOSS_MODULES_SYSTEM_PKGS" = "x" ]; then
   JBOSS_MODULES_SYSTEM_PKGS="org.jboss.byteman,org.graalvm.visualvm"
fi

For domain mode, locate the system-properties element in domain.xml file and add a property named jboss.modules.system.pkgs with a value of org.graalvm.visualvm to the existing system properties. For example:

<system-properties>
        <property name="jboss.modules.system.pkgs" value="org.graalvm.visualvm"/>
</system-properties>

Then, we need to provide the JFluid jar files to WildFly Runtime. A handy option is to make this library available as part of a global directory which is scanned at start by WildFly. Let’s see how to do that. Connect to WildFly CLI:

$ ./jboss-cli.sh -c

Then execute the following command (replace the path with the actual path where VisualVM has been installed)

/subsystem=ee/global-directory=profiler:add(path=/home/jboss/visualvm_206/visualvm/lib)

The following configuration will be added to your WildFly server:

<subsystem xmlns="urn:jboss:domain:ee:5.0">
    <global-directories>
        <directory name="my-common-libs" path="/home/jboss/visualvm_206/visualvm/lib"/>
    </global-directories>

To connect to a WildFly JVM running on the same machine as VisualVM:

  • Open VisualVM, and find the `Applications` panel on the left side of the VisualVM window.
  • Under `Local`, double-click the WildFly JVM process that you want to monitor.

For a standalone WildFly server, there is one WildFly JVM process.

VisualVM monitoring performance WildFly

A WildFly managed domain host has multiple JVM processes you can connect to: a *Host controller* JVM process, a *Process controller* JVM process, and a JVM process for each WildFly *Server* on the host. You can find out the list of active Java processes using the jps command as follows:

$ jps -lv

5469 /home/jboss/wildfly-22.0.0.Final/jboss-modules.jar -D[Standalone] -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m 

Right-click on the WildFly server connection and choose Open. Once connected, the following tabs will display in the Main window:

VisualVM monitoring performance WildFly

From each tab, the following options will be available:

  • `Overview`: This tab shows generic server info like JVM arguments and system properties.
  • `Monitor`: This tab reveals a real-time set of graphs which collect data for the CPU, memory utilization, classloading, and threads used.
  • `Threads`: This tab provides a detailed view of all threads running in the JVM along with their state (Running, Sleeping, Wait, and Monitor).
  • `Profiler`: This tab enables you to instrument a profiling session of a local application.
  • `Sampler`: This tab enables to capture Heap snapshots periodically and display memory/cpu statistics per class.

The standard monitoring options are straightforward to use and don’t need an accurate guidance. In order to pinpoint performance issues, you should rather focus on the Profiler and Sampler options.

Troubleshooting VisualVM Connection issues

If your connection to the WildFly process is hanging on and you are sure the connection should work (i.e. you double checked all the standard things like firewalls, network configuration etc.) the RMI system property java.rmi.server.hostname is something to try:

$ ./standalone.sh -Djava.rmi.server.hostname=localhost

Besides it, it’s worth checking the Network options of VisualVM. Verify that your Proxy settings are set to “No Proxy” or, as an alternative, that the target host is in the list of excluded proxy hosts.

Found the article helpful? if so please follow us on Socials