What's New in JProfiler 10.1

Change release:

Please see the change log for a detailed list of changes.

JProfiler 10.1 introduces the following notable new features:

The documentation has been rewritten from the ground up. Instead of the old reference-style documentation that focused on explaining all the UI elements, the new documentation is in the form of a book that can be read sequentially. Plenty of screen shots illustrate the context of each chapter.

In addition to the HTML and PDF formats that are included in the JProfiler distribution, the documentation is now also available as an eBook in epub and Kindle formats. The eBook files can be downloaded from the web site.

With the F1 key, you can show the most relevant chapters of the book directly from the UI. Many UI elements now have adjacent help icons that show tool tips with detailed explanations.

Custom probes have been redesigned from scratch. There are now two separate probe APIs for two fundamentally different use cases.

The injected probe API replaces the old custom probe API. You can use it to write probes for 3rd party components. Injected probes are configured with annotations, each interception is defined by an annotated method in the probe class. Both payload interceptions like SQL strings of the JDBC probe or call tree splitting interceptions like URLs of the servlet probe are supported.

An injected probe can be as simple as

@Probe(name = "My probe")
public class MyProbe {
    @PayloadInterception(invokeOn = InvocationType.ENTER,
            method = @MethodSpec(className = "x.y.z", methodName = "importantMethod",
                    parameterTypes = {"java.lang.String"}, returnType = "void"))
    public static String measure(@Parameter(0) String payload) {
        return payload;

Examples of injected probes are available in the "api/samples" directory. "simple-injected-probe" shows how to get started and "advanced-injected-probe" showcases other features of the API.

Embedded probes are intended to add probes to your own code. The probe is set up by deriving a configuration class that also serves as a probe ID. Instead of having to define intercepted methods, you then call the embedded probe API directly:

String payload = ...;

// for adding payloads like SQL strings of the JDBC probe
Payload.execute(MyProbe.class, payload, () -> {
    // perform work and measure the execution times

// for splitting the call tree like URLs of the servlet probe
Split.execute(MyProbe.class, payload, () -> {
    // perform work

An embedded probe is part of your software and automatically appears in JProfiler without any additional configuration if a JVM is profiled and the probe class is loaded. Calling the embedded probe API adds next to no overhead in production because its method bodies are empty and are only wired up to actual code if the profiling agent is present.

Like for the injected probes, there is a "simple-embedded-probe" example for getting started and an "advanced-embedded-probe" example for a broader look at the features of the API.

The new documentation has chapters for both injected and embedded probe APIs and the Javadoc contains detailed information for all features. The probe API artifacts are available as Maven dependencies and are licensed under the Apache 2.0 license.

With script probes, you can define payload probes directly in the JProfiler UI. They replace the old custom probes and are are a lot easier to configure. For each method interception, you can configure a script that returns the intercepted payload as a string.

The context menu of the call tree contains an action that makes it easy to select the intercepted method for a script probe.

Each script probe adds a new view in the "JEE & probes" section with payload hot spots, default telemetries and probe event views.

A Gradle plugin has been added. The Gradle plugin is loaded from the Gradle plugin portal, but does not include the JProfiler distribution. To use any JProfiler Gradle task, start your build script with

plugins {
    id 'com.jprofiler' version 'X.Y.Z'
jprofiler {
    installDir = file('/path/to/jprofiler/home')

With the profiling task and a pre-configured session that includes triggers, you can automate profiling session in your build process:

task run(type: com.jprofiler.gradle.JavaProfile) {
    main = 'com.mycorp.MyMainClass'
    classpath sourceSets.main.runtimeClasspath
    offline = true
    sessionId = 80
    configFile = file('config/config.xml')

There are also tasks for command line export and command line comparisons, as well as pre-analyzing snapshots with heap dumps.

The merged reference views in the heap walker have been re-implemented and are now much more usable and helpful. The views now show reference holders and referenced objects on each node and make the referencing relationship much clearer.

In addition, the references can be grouped by class instead of by field. This is the new default mode for the merged reference views. Many non-standard collection types that are not directly supported by the compact reference types in JProfiler are collapsed automatically in this way.

At each node in the merged incoming references view, you can select the objects in the current object set that are referenced in this way or the reference holders for the particular node.

A merged dominating references view has been added to the heap walker. Unlike the merged incoming references, the merged dominating references show which references have to be eliminated to make some or all objects in the current object set eligible for garbage collection.

In the case of multiple independent GC roots, some or all of the objects in the current object set may not be referenced through dominating references, so the view can be empty. The merged dominating references use the same data as the biggest objects view, so references can be transitive, without direct references between parent and child nodes.

The merged dominating references view can show references from the current object sets towards the GC roots or vice versa. Depending on whether the references that you want to eliminate are close the the objects in the current object set or close to the GC roots, one or the other mode is more convenient.

In the heap walker, class and class loader grouping in the biggest object view have been added. If you have many biggest objects of the same class, it is useful to switch to class grouping to get a better picture.

If class loaders are an important aspect of your investigation, the class loader grouping will help you find out where the classes of the biggest objects are coming from.

The MongoDB Async Driver is now supported. In the MongoDB probe, asynchronous executions of code are tied to the stack traces that triggered the database operation. Whether the synchronous or asynchronous driver is used, is indicated by the first node below a hot spot or the first node of a stack trace in the events view.

A probe telemetry overview has been added that combines all telemetries of the probe. Just like for the overview of the standard VM telemetries, you can click on the telemetry name to show the full view.

Quick search in the node detail dialog has been implemented. The node detail dialog is an important tool for probes where the payload strings can be very long, for example the SQL statements in the JDBC view. When moving the mouse over the text area, actions for quick search and copying all text to the clipboard become visible.

While profiling Java 9 was already supported by JProfiler 9, the JProfiler UI and all command line tools can now run on Java 9. This is especially relevant for Linux desktops where the JProfiler UI can now make use of the new HiDPI support in Java 9.

JProfiler makes a lot of use of scripts that are entered directly in JProfiler. Now you can select a Java 9+ JRE to compile these scripts.

Also, starting with this release, Java 10 can be profiled with all features supported by JProfiler.