What's new in JProfiler

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

JProfiler 16.22026-07-16change log

Offline profiling can now be configured directly in the -agentpath VM parameter, without a JProfiler config file. Previously, offline mode required you to export a session configuration from the JProfiler UI first.

You can specify the most common profiling settings inline: the call tree collection mode with callTreeMode and the profiled, compact and ignored package filters with profile, compact and ignore. On top of that, you can add a complete automated recording sequence that saves a snapshot without any API calls or jpcontroller, using the snapshot, recording, duration and delay options.

For example, the parameter

-agentpath:...=offline,callTreeMode=sampling,profile=com.mycorp.,\
    snapshot=/tmp/snapshot.jps,recording=cpu:allocation,duration=10m

records CPU and allocation data for ten minutes and then saves a snapshot.

The same inline settings and recording options are also available for the jpenable command line tool, which attaches the profiling agent to an already running JVM. When you select offline mode, jpenable guides you through the settings with its interactive rich console.

ScreenshotScreenshot

Alternatively, you can supply the settings on the command line with --call-tree-mode, --profile, --line-numbers, --snapshot, --recording, --duration and more for non-interactive use in a CI pipeline.

The Gradle and Ant profiling tasks expose the same capability through task attributes, so you can configure offline profiling and automated recording sequences right in your build script.

The MCP server introduced in JProfiler 16.1 has been improved. It now works reliably with weaker models and follows the profiling workflow more robustly. Antigravity has been added as a supported AI coding tool.

JProfiler 16.12026-04-09change log

JProfiler now ships with an MCP (Model Context Protocol) server that lets AI coding agents profile your Java applications, analyze the results, and act on them. It works with Claude Code, Cursor, Codex, Gemini CLI and any other MCP-compatible AI coding tool.

Until now, profiling has been something you do with a GUI: you start a session, navigate views, and interpret data. With the MCP server, an agent can close the loop on its own. It profiles an application, discovers that JDBC queries dominate execution time, modifies the code to eliminate redundant database calls, re-profiles to verify the improvement, and presents a before-and-after comparison with concrete numbers.

ScreenshotScreenshot

The tools exposed by the MCP server have been carefully crafted and tested so that agents reliably follow a profiling workflow that mirrors how an expert would use JProfiler. The agent first sets up profiling for the target application. After the test run completes, it checks for data availability and retrieves the initial aggregated hotspot view to understand where time is being spent. From there, it drills into specific hotspots, following the call chain to the root cause.

The data at each step is carefully filtered so agents see what matters without being overwhelmed, whether they are analyzing CPU hotspots, JDBC and JPA queries, HTTP calls, MongoDB operations, or heap dumps. Beyond live profiling of local and containerized JVMs, agents can also load existing JProfiler, HPROF, or JFR snapshots for analysis.

ScreenshotScreenshot

Setup is zero-friction: the MCP server auto-installs the JProfiler binary on first use and handles licensing through the MCP protocol. You can set up your agent directly from the JProfiler UI, or follow the instructions on the MCP setup page. For the full story behind this release, see the announcement blog post.

JProfiler 16.02026-02-27change log

JProfiler 16 introduces an AI probe. The probe measures interactions with LLMs via LangChain4j and Spring AI.

Chat requests and embeddings are supported and shown in the events view as different event types.

Details for the processed instructions are available in the node detail dialog that can be shown with the hover button in the instructions column. The instructions column shows statistics for the different instruction types, such as user messages, assistant messages, or tool messages.

ScreenshotScreenshot

The AI probe is event-centric. You can work with subsets of recorded events in two ways: First, when you select multiple events, the selection panel at the bottom provides CPU hot spots, probe hot spots, and a probe call tree for the current selection.

ScreenshotScreenshot

For more thorough investigations, the filter selector at the top and the various tabs in the lower section allow you to restrict the set of events in the main table and associated views.

ScreenshotScreenshot

By default, the AI probe identifies hot spots based on the specific model names that processed the request. This data is available not only in the events view, but also in the hot spot view of the AI probe, even if no events are recorded.

ScreenshotScreenshot

Model name hot spots are only one of many potentially interesting types of hot spots. In the probe settings, you can configure a script to calculate user-defined types of hot spots by entering some Java code in JProfiler's powerful script editor.

ScreenshotScreenshot

When an AI probe event is recorded, JProfiler invokes this script with a ModelRequest parameter. This parameter provides access to the request type, the model name, and all instructions along with their instruction types.

For example, you could define hot spots by grouping prompt lengths into 50-character buckets. The example below demonstrates how this is done.

ScreenshotScreenshot

Since JProfiler displays data live during recording, you can change these settings while profiling and observe the effects immediately.

With the above script, the new hot spots look like this:

ScreenshotScreenshot

By default, hot spots focus on the request duration, but you can switch the primary measurement to input tokens and output tokens as well.

This is possible both in the probe hot spots view and the probe call tree view. The probe call tree view shows a top-down view connecting method calls to probe payloads.

ScreenshotScreenshot

The probe telemetries for the AI probe show request counts, average request duration, and a combined input/output token graph separately for chat requests and embedding requests.

ScreenshotScreenshot

Each telemetry can be shown separately and can be used to select events for particular areas of interest.

ScreenshotScreenshot

To help you explore the AI probe, JProfiler now comes with an "LLM demo" session.

It uses Jlama, a cross-platform inference engine for Java 21+ and downloads a 0.5-billion-parameter model from Hugging Face to categorize LLM-related preprints from arXiv.

The demo features a UI where keywords produced by the LLM are continually inserted and you can explore the associated research papers on the right.

ScreenshotScreenshot

JProfiler has a new UI with a modern visual appearance and new icons. We hope you like it! We have light and dark themes. You can see screenshots of them by toggling the dark mode switch at the top of this page.

ScreenshotScreenshot

In addition, the UI is now fully scalable. In the general settings, you can either set a scale factor as a percentage, or set a custom UI font with an arbitrary size, and the UI will be scaled accordingly.

ScreenshotScreenshot

This capability now allows the JProfiler UI to run on Linux with all OpenJDK variants and for all HiDPI resolutions. Previously, only the JetBrains runtime was supported on Linux with HiDPI resolutions.

The JProfiler installer has been modernized, and its default execution mode has been streamlined. By default, no admin privileges are requested unless you choose to install for all users in its customized execution mode.

ScreenshotScreenshot

As a related enhancement, it is now possible to attach to Windows processes running as other users, even if JProfiler is not installed in a directory that is readable by those processes. This is especially important for attaching to Windows services.

ScreenshotScreenshot

JProfiler's probe event recording has been reimplemented. This brings scalability to many millions of events and many new features.

When probes were introduced in JProfiler 7, the focus was on cumulative data, like hot spots and telemetries. Single events were available as a tool for debugging problems, but they were all held in memory, so they were limited to relatively low event counts.

However, keeping all events enables advanced filtering that is impossible to achieve using aggregate data alone. The new file-based backend supports high-throughput recording, enabling complex queries across massive event sets that were previously impossible to process.

The new timeline tab at the bottom of the events view shows a histogram of all recorded events and allows you to select a time range for filtering.

ScreenshotScreenshot

While the table only shows a limited number of events, you can add more events when scrolling to the bottom. When sorting by a column, the entire set of filtered events is considered, not just the currently visible rows.

Totals in the table are also calculated for the entire set of filtered events.

ScreenshotScreenshot

The lower "Hot Spots" tab contains a CPU hot spots view, a probe hot spots view, and a probe call tree – similar to the "Selection" tab, but calculated for all filtered events rather than the selected rows.

In each of these views, you can use the filter button to restrict the displayed events for the main event table and all other views at the bottom. Below you can see a call stack filter in the probe call tree where the filtered node is marked with a filter icon.

ScreenshotScreenshot

Depending on the measurements performed by a probe, additional histogram views are available at the bottom. For the "Files" and the "Sockets" probes these are "Duration" and "Throughput".

Histograms can be shown with a logarithmic y-axis and support filtering by dragging a range with the mouse.

ScreenshotScreenshot

Finally, smart column management in the events view has been implemented. Based on the width of all columns and the available viewport width, JProfiler decides whether to fit the columns into the viewport or activate horizontal scrolling. Resizing columns manually disables the "fit-to-viewport" mode, which automatically reactivates if the total table width becomes smaller than the viewport.

The probe call tree and probe hot spots views now have a metric selector if a probe has additional measurements beyond event duration. For example, the "Files" and the "Sockets" probes also offer "Read Throughput" and "Write Throughput". Selecting one of the throughput metrics automatically restricts the view to "Read" or "Write" events, respectively.

Changing the metric recalculates hot spots and updates the hot paths in the probe call tree.

ScreenshotScreenshot

Metric selectors are now also available on the "Selection" and "Hot Spots" tabs of the probe events view. Since "Read" and "Write" events can be filtered separately in the events view, there is a single combined "Throughput" measurement.

ScreenshotScreenshot

JProfiler 16 delivers many improvements for JFR support.

  • Responsiveness in the event browser for large event counts has been improved by pre-calculating the data in the lower views.
  • Previous versions of JProfiler only handled a maximum number of events in the event table. You can now load additional events by scrolling to the bottom. Additionally, when sorting the table, all filtered events are considered rather than just the visible subset.
  • The totals in the event table are now calculated for all filtered events, not just for the currently displayed ones.
ScreenshotScreenshot

Support for throttle settings has been added in the JFR recording wizard. For example, the new jdk.CPUTimeSample event in Java 25 is configured via throttling. You can alternatively enter a period or an emission rate with a /s unit.

ScreenshotScreenshot

Throttle settings are also displayed in the CPU views next to the thread status selector.

ScreenshotScreenshot

For calculating data in the CPU section, the new Linux-only jdk.CPUTimeSample event (Java 25+) is now used if recorded, instead of the older jdk.ExecutionSample event. Unlike jdk.ExecutionSample, which works on all platforms, but has limitations in the number of threads it samples and the accuracy of CPU usage, jdk.CPUTimeSample uses CPU time events from the Linux kernel to collect data.

With this event, CPU profiling with JFR can now provide actionable CPU metrics on production systems where loading a JVMTI agent is not permitted.

ScreenshotScreenshot

Starting with JProfiler 16, all experimental JFR events are now shown in the event browser, such as the jdk.CPUTimeSample event.

ScreenshotScreenshot

JProfiler 16 introduces support for virtual thread dumps.

The thread dumps view now features two distinct actions: one for platform thread dumps and another for virtual thread dumps.

While the virtual thread dump also includes platform threads, it is asynchronous, so synchronous platform thread dumps are preferable when not working with virtual threads.

ScreenshotScreenshot

Virtual threads are hierarchically organized within their thread containers. This is relevant when using structured concurrency, which is still a preview feature as of Java 25.

In structured concurrency, each scope creates a corresponding thread container. Since a dump may contain millions of virtual threads in deeply nested containers, virtual thread dumps can be significantly larger than platform thread dumps.

ScreenshotScreenshot

You can compare two single virtual threads or two entire thread dumps by selecting them and choosing the comparison action in the context menu.

ScreenshotScreenshot

The comparison is shown in a diff viewer in a separate window.

ScreenshotScreenshot

To copy single threads, multiple threads, or entire thread dumps to the clipboard, use the corresponding action in the context menu.

ScreenshotScreenshot

Virtual thread dumps group threads with the same stack trace in the same hierarchical position into a single node.

The context menu contains an action to show all grouped thread names.

ScreenshotScreenshot

The names of grouped threads are displayed in a separate window where you can filter for thread names of interest.

ScreenshotScreenshot

Thread grouping is also supported for platform thread dumps.

You can now analyze the contribution of single threads in a cumulative call tree. In the call tree view, select "Show Threads" from the context menu to calculate this data for the selected node.

ScreenshotScreenshot

A separate dialog with a percentage breakdown of all contributing threads is shown. You can optionally select one thread and switch to the call tree for that thread in the call tree view.

The feature helps identify thread-specific performance issues. For example, you may want to isolate a misbehaving thread from a thread pool.

ScreenshotScreenshot

The node detail dialog was improved in several ways.

The node detail dialog is an important tool to display more information for selected elements and is available from the "View" menu or the context menu.

When selecting multiple nodes in hot spots views, cumulative statistics for the selection are now displayed.

ScreenshotScreenshot

Many tables in JProfiler have columns containing long text that exceeds the column width. The node detail dialog shows the complete text in this case. Starting with JProfiler 16, there is a hover button that directly opens the node detail dialog and activates the correct tab if there are multiple long text columns in the table.

ScreenshotScreenshot

In the heap walker, the node detail dialog now shows the full values for string values in the reference views, not just the displayed truncated preview string.

ScreenshotScreenshot

JProfiler now supports deobfuscation for snapshot comparisons.

Previously, when comparing snapshots from an obfuscated application, there was no way to deobfuscate classes and methods. Below, you can see an example of a comparison using obfuscated names.

ScreenshotScreenshot

Similar to the existing deobfuscation support when opening snapshots, the file chooser now includes a "Deobfuscate" check box when adding snapshots to the comparison window.

ScreenshotScreenshot

When selected, a dialog with a drop-down for supported obfuscators and a field for the mapping file path appears.

If different snapshot files have different mapping files, you can add the snapshots individually.

ScreenshotScreenshot

Once the mapping file is applied, all comparisons in JProfiler now show the original class and method names.

ScreenshotScreenshot

Timeline views now support row pinning.

In the threads history view and in all the probe timeline views, you can pin selected rows via the context menu. These are shown in a separate area at the top where you can use drag and drop to change their order.

ScreenshotScreenshot

You can unpin pinned rows individually or all at once.

ScreenshotScreenshot

JProfiler 16 also introduces a sorting drop-down that offers ascending and descending sort directions and a new default sort mode where active long-lived rows are shown first, followed by recently closed rows.

ScreenshotScreenshot

JProfiler 16 adds full support for profiling Java 26.

This version is essential if you are profiling virtual threads or if you are using the new built-in HTTP/3 support in the JDK HTTP client.

JProfiler 15.02025-03-27change log

Probes for Apache Kafka were added. The probes measure various types of data that help you to identify bottlenecks, optimize configurations, and maintain the health of your data streaming infrastructure.

To handle both client and server separately, there are separate probes for Kafka consumers and Kafka producers. The "Kafka producer" probe analyzes the events that you publish.

A starting point for handling many kinds of problems is the "Hot spots" view where you can open hot spot nodes to see the back traces into your code.

ScreenshotScreenshot

The "Kafka consumer" probe measures the events that you process. For Spring Kafka, event timings are recorded.

ScreenshotScreenshot

Single events can be analyzed in the "Events" view, where values for event type, thread name, partition, key and value size are also shown.

ScreenshotScreenshot

The Kafka probes contribute several telemetries, like "Event count" and "Average listener execution time" that can also be added in the main "Telemetries" view section.

ScreenshotScreenshot

Both probes offer the same flexibility for naming hot spots and events. By default, hot spots are named with the message topic. You can use a script to build the strings for the hot spots yourself using an API provided by JProfiler. Naming hot spots is important because it determines the grouping in the hot spots view.

Optionally, you can use a different script for the naming of single events in the "Events" view. This will not affect hot spot grouping and is a way to provide more detail for debugging.

ScreenshotScreenshot

Recording events from either probe adds data in the regular call tree views in the "CPU views section". For the "Kafka producer" probe, hyperlinks are inserted into the call tree for revealing the associated call stack in the call tree view of the probe.

ScreenshotScreenshot

The Kafka consumer probe splits the call tree for Spring event listeners, so you can see the subtree for different types of messages separately. The grouping is done with the configured "hot spots" naming.

ScreenshotScreenshot

An IDE integration for Visual Studio Code has been added. It is available in the Visual Studio Marketplace and works together with a local installation of JProfiler.

If the VS Code plugin cannot find the JProfiler installation automatically, it will ask you to locate it the first time you start a profiling session.

Screenshot

The extension adds two actions: With "Enable Profiling with JProfiler" you toggle the profiling mode, so that all debug and run actions will start profiling for Java launch configurations. With "Attach to a running JVM with JProfiler" you can use the attach mode feature for local or remote JVMs and get source code navigation into VS code.

ScreenshotScreenshot

Depending on the status of this pull request for the vscode-gradle plugin, profiling Gradle tasks is also supported by the "Enable Profiling with JProfiler" action.

The JProfiler plugin only has a few settings, notably for the location of the JProfiler executable and a setting whether to open new windows for new profiling sessions.

ScreenshotScreenshot

All other profiling settings are handled by JProfiler and stored on a per-project basis. When you start a profiling session, the session startup dialog gives you a chance to view and modify all settings in one place.

When profiling unit tests, JProfiler will automatically suggest saving and immediately opening a snapshot when the JVM exits.

ScreenshotScreenshot

Switching to VS code when working with the JProfiler UI is seamlessly possible with the "Activate IDE" action (F11).

ScreenshotScreenshot

To show the source code of a selected class or method, use the "Show source" action that is visible everywhere in JProfiler. The VS Code UI will be brought to the front, and the associated source code will be shown.

ScreenshotScreenshot

Another useful feature provided by the JProfiler VS Code plugin is that you can open JProfiler, HPROF and PHD snapshots from inside VS Code to get source code navigation from the JProfiler UI into VS Code.

ScreenshotScreenshot

An alternative SSH mode via OpenSSH has been added. This is important for being able to profile JVMs on all types of remote machines without any configuration.

JProfiler ships with a built-in SSH client for SSH connections that supports password and public key authentication. To support other authentication types and complex network topologies, a new SSH tunnel type was added, that uses your local OpenSSH installation.

ScreenshotScreenshot

For example, if you want to connect to an EC2 instance via AWS session manager, the built-in SSH client does not work because it cannot tunnel through an arbitrary proxy. In the AWS documentation, you get a list of options that you can either add to the OpenSSH config file or directly on the command line, both of which work with the new OpenSSH mode in JProfiler. This involves a ProxyCommand option that tunnels the connection through the aws executable. In the screenshot below, the "SSH options" text field contains these arguments.

ScreenshotScreenshot

The only required input for the OpenSSH mode is the host name.

In the case where you use the OpenSSH config file to define your fully configured SSH servers, you can easily select them with the "Choose" button next to the "Host" text field.

ScreenshotScreenshot

An alternative netcat SSH mode has been added for SSH hosts where port forwarding is disabled.

Many security-hardened production systems disable SSH port forwarding. In those cases, previous versions of JProfiler could not establish an SSH tunnel through such machines. While SSH port forwarding is still the preferred option for SSH connections due to its stability and better error reporting, JProfiler 15 adds a "netcat mode" that can optionally be enabled to fix this issue.

ScreenshotScreenshot

When a connection fails in such a way that disabled port forwarding may be to blame, JProfiler suggest switching to the netcat mode.

ScreenshotScreenshot

JProfiler can now take MBean snapshots. This is especially useful if you save JProfiler snapshots, either from the UI or during offline profiling. MBean snapshots enable you to use the MBean browser when JProfiler is not attached to the live JVM.

In live mode, the "MBean snapshot" action in the toolbar creates a new snapshot that is then shown in the view selector. You can take multiple snapshots and switch between them.

ScreenshotScreenshot

MBean snapshots can be assigned labels that are displayed in the view selector. Unwanted MBean snapshots can also be removed again.

ScreenshotScreenshot

When you take an MBean snapshot, a bookmark is added to all views that have a time axis.

ScreenshotScreenshot

If you set a filter for the displayed MBeans, only the displayed subtrees will be included in the snapshot.

ScreenshotScreenshot

In the MBean snapshot trigger action, you can set a label as well as a filter for the included MBeans as well.

ScreenshotScreenshot

You can now take multiple "all objects" dumps.

The "All objects" view now has an action to take snapshots of the class histogram for all objects on the heap. When two dumps are selected, the differences are shown in the view.

ScreenshotScreenshot

The toolbar above the dump selector offers actions to label and remove selected dumps.

ScreenshotScreenshot

A trigger action has been added to take all object dumps programmatically, either in live mode or during offline profiling.

ScreenshotScreenshot

On a related note, it is now possible to label dumps in the thread dumps view as well. This can also be done via the trigger action and the Controller API.

ScreenshotScreenshot

You can now make snapshots of the "Call tree" view in the CPU section.

For that purpose, a "Call tree snapshot" action has been added to the call tree analyses drop-down.

ScreenshotScreenshot

It creates a new call tree analysis view below the main call tree view that shows a static copy of the selected root, or the entire call tree if no node was selected. All other view parameters like thread status or aggregation level are fixed in the call tree snapshot.

Unlike other call tree analyses, call tree snapshots are saved into JProfiler snapshots, because they contain separate data.

With this tool, you can manage different call tree recordings without resorting to saving full snapshots that you have to open in different JProfiler windows. Instead, you can remain in the same live session and keep different sets of recording data around.

ScreenshotScreenshot

In the call tree snapshot view, a "Calculate hot spots" analysis action is available besides the usual call tree analysis types.

ScreenshotScreenshot

The resulting hot spot view is added as a child of the call tree snapshot view and shows the static hot spots for the data in the parent view. The hot spot calculation options are still adjustable here.

ScreenshotScreenshot

Call tree analyses have been improved.

You can now rename call tree analyses. After making them permanent with the pin button, a rename button will appear that changes the name of the analysis in the view selector.

ScreenshotScreenshot

In addition, the "Reload analysis" button goes back to the top level ancestor view and re-calculates all ancestor views and all descendant views for the new data. In the example below, the current data in the live call tree would be used to update the call tree view labeled "First run" and then the flame graph views labeled "Reload" and "Render".

ScreenshotScreenshot

Heap walker filter and grouping scripts on dumped data have been added.

Previously, only filter and grouping scripts on live objects were available which did not work for snapshots. Also, changing data and garbage collection of objects may require operations on dumped data instead of live data.

In the references view of the heap walker, the "Apply filter" dropdown contains a new action to filter objects by running a script on dumped data.

ScreenshotScreenshot

In the script editor, objects from the com.jprofiler.api.agent.heap API are passed as an argument, and the boolean return value of the script decides whether the object is included in the new object set.

In general, the parameter is of type com.jprofiler.api.agent.heap.HeapObject but can be narrowed to a subtype if the current object set allows it. In the screenshot below, the current object set only contained java.util.HashMap$Node instances, so the parameter is of type com.jprofiler.api.agent.heap.Instance which provides access to field values.

ScreenshotScreenshot

The script selects java.util.HashMap$Node instances whose value is a java.awt.Font with a size of 12.

ScreenshotScreenshot

In addition to the filter script in the references view, JProfiler provides an inspection to filter all objects in the current object set as well an inspection which groups all objects according to the string return value of a script.

ScreenshotScreenshot

In the "Custom grouping on dumped data" script below, all regular instances are grouped by the number of strings that they reference. If the passed object is not a regular instance or if it does not reference any strings, the script returns null and the object is not included.

ScreenshotScreenshot

As for other kings of groupings, a grouping selector is shown at the top after the inspection has been calculated. When you select a group row, the current heap walker view will only show the instances that are contained in that group.

ScreenshotScreenshot

JProfiler 15 makes it easier to see which views contain data.

For snapshots, all views without recorded data are now shown as disabled in the view selector.

ScreenshotScreenshot

With the new "Next enabled view" and "Previous enabled view" actions, you can quickly step through all relevant views.

ScreenshotScreenshot

For live sessions, the views displaying recorded data now have a special marker in front of the view name.

ScreenshotScreenshot

A Japanese locale has been added. こんにちは、日本!

The UI as well as the documentation have been fully localized into Japanese. The language can be changed in the general settings and will be auto-detected by the installer.

ScreenshotScreenshot

A Korean locale has been added. 안녕하세요, 한국!

The UI as well as the documentation have been fully localized into Korean. The language can be changed in the general settings and will be auto-detected by the installer.

ScreenshotScreenshot

Thread IDs are now shown in the UI.

Previously, only thread names were displayed which are not necessarily unique. Now the unique ID of each thread is added, so that you can identify particular threads under all circumstances.

ScreenshotScreenshot

The process for handling a download failure of JProfiler agent archives for remote profiling has been improved.

During a zero-configuration remote attach operation, JProfiler needs to upload the profiling agent for the remote platform. If the agent for the remote architecture is not available, JProfiler will download and cache it locally. In the case of restrictive firewalls, such a download may not be possible.

While previous workarounds were cumbersome, JProfiler 15 now offers a workflow for procuring the agent archive with a browser and telling JProfiler about the externally downloaded archive.

ScreenshotScreenshot
    JProfiler 14.02023-09-07change log

    JProfiler 14 adds full support for profiling Java 21, including virtual threads. Java virtual threads are thread-like tasks that aim to revolutionize high-scale concurrency on the JVM. All aspects of JProfiler have been reworked so that profiling millions of virtual threads causes minimal overhead.

    In the call tree, virtual thread executions will have a top-level node of java.lang.VirtualThread.

    ScreenshotScreenshot

    Virtual threads are not recorded separately like platform threads, so all virtual threads are contained together in a single synthetic thread group.

    ScreenshotScreenshot

    By default, only mounted virtual threads are sampled. This means that blocking states of virtual threads are not captured by CPU recording. For debugging purposes, there is an option in the profiling settings to sample unmounted virtual threads.

    ScreenshotScreenshot

    Like for platform threads, JProfiler supports async tracking for the creation of new virtual threads. If enabled, the "Inline Async Executions" call tree analysis connects call sites with execution sites. In this case, the call site is the last profiled method before the VirtualThread instance is created. The execution site is a top-level node in the started virtual thread.

    ScreenshotScreenshot

    Near-zero overhead for full sampling when profiling Java 17+. Using new facilities in the JVM, JProfiler can now perform sampling with a negligible overhead, even for heavily multi-threaded applications where the overhead for sampling used to be significant.

    From an overhead perspective, sampling is now on equal terms with async sampling if you profile Java 17 or higher.

    ScreenshotScreenshot

    A garbage collector probe was added. The GC probe is available when profiling Java 17+ and shows detailed data about single garbage collections and the GC configuration.

    Because of the increasing number of probes, the probe sections have been reorganized and the GC probe can be found in the new "JVM & Custom Probes" section.

    ScreenshotScreenshot

    Its main view is the "Garbage collections" view that shows single garbage collections in tabular form. It shows you the triggering cause, how long the collection took, how many references were collected and what pauses were caused by the garbage collection.

    ScreenshotScreenshot

    If you need even more detail, each garbage collection can be expanded to show the single phases with their duration. To the right of the GC phase table, statistics about the changes in heap and metaspace are shown.

    ScreenshotScreenshot

    To help you analyze important garbage collections, you can set multiple filters, most conveniently with the context actions on the garbage collections table and the phase table. Filters are added as tag labels above the table and can be removed by clicking their close button.

    ScreenshotScreenshot

    The GC probe produces a number of GC telemetries which are available in the "Telemetries" probe view.

    ScreenshotScreenshot

    If you are interested in minimizing GC pauses, the "Longest pause" telemetry at the top will be the most interesting one. You can drag along the time axis of the telemetry to select the corresponding garbage collections in the "Garbage Collections" view. For better vertical resolution, you can select a single telemetry from the drop-down at the top or by clicking on the name of the telemetry.

    ScreenshotScreenshot

    The GC summary view shows you measurements that are aggregated over the entire recording period. Each measurement provides the number of garbage collections, as well as the average, maximum and the total values. The most important data at the top are the "Pause times" that directly affect the liveness of your application.

    ScreenshotScreenshot

    In the GC configuration view, you can inspect the common properties that can either be set explicitly or that are set implicitly by the garbage collector itself. These properties are common to all garbage collectors and help you understand the differences between garbage collectors.

    ScreenshotScreenshot

    Finally, the GC flags view gives you an idea what properties of a garbage collector can be tuned and lets you check their actual values. The "Origin" column shows you how the flag was set.

    ScreenshotScreenshot

    A gRPC probe has been added. gRPC is a popular RPC framework that uses HTTP/2 and Protocol Buffers, offering features like streaming and multiplexing. This probe can be found in the new "HTTP, RPC & JEE" probe section.

    ScreenshotScreenshot

    JProfiler can track remote gRPC calls between JVMs if gRPC remote request tracking is enabled.

    ScreenshotScreenshot

    You can then see hyperlink labels in the call tree view for incoming and outgoing calls that will take you to the corresponding call tree location. This requires that both JVMs are profiled in separate windows or snapshots are opened that were recorded during the remote call.

    ScreenshotScreenshot

    JProfiler 14 adds first-class support for JDK Flight Recorder (JFR) snapshots. The centerpiece of this support is the new JFR event browser.

    JFR is a structured logging tool that records a broad range of system-level events. Similar to the black box of an aircraft that continuously records flight data for use in incident investigations, JFR continuously records a stream of events in the JVM for use in diagnosing problems.

    Events are categorized hierarchically and shown in the tree on the left side, single events are displayed in the table on the right. The columns of the event table and the analysis views below it depend on which event types have been selected.

    ScreenshotScreenshot

    In the selection area, the stack trace of the selected event is shown if it was recorded. If you select multiple events, a call tree or a hot spots view is shown for them. If the selected event types have time, memory or frequency measurements, you can choose to calculate the hot spots for any of those measurements.

    ScreenshotScreenshot

    To avoid overloading the UI, the event table only shows a maximum of 10000 events. The analysis views operate on all events in the snapshot. Due to the nature of JFR recording, JFR snapshots can become very large, so JProfiler's event browser has been optimized for maximum speed even for extreme file sizes.

    The "Hot Spots" and the "Call Tree" views are like their counterparts in the "Selection" area, but for all events of the selected event types. Also, you can add call stack filters and hot spot filters and an optional back trace part.

    ScreenshotScreenshot

    Any analysis view itself is calculated from all filtered events, but excluding the filter that was set in the analysis view itself. This makes the analysis view more useful because you can see what part of the total event set you have selected there.

    The "Time Line" view shows a histogram of all event start times. You can select a time range with the mouse and filter the events in the table. By default, the view has a logarithmic vertical axis.

    ScreenshotScreenshot

    For each event column that contains a durations, memory sizes or a frequency, JProfiler adds a histogram view. Histograms show event counts on their vertical axis while the horizontal axis shows the selected measurement. Bin sizes and event counts are available from the tooltip. Event filters can be added in histogram views by selecting a range on the horizontal axis.

    ScreenshotScreenshot

    The view settings dialog of the event browser allows you to customize the views. For example, the scales for the columns that are currently shown can be adjusted there.

    ScreenshotScreenshot

    Apart from the JFR browser, a subset of JProfiler's views that match with data provided by JFR are available when opening snapshots. This is a capability that JProfiler already had before. In addition, the new garbage collector probe is now available for JFR snapshots.

    ScreenshotScreenshot

    Along with the first-class support for opening JFR snapshots, JProfiler adds support for recording JFR snapshots directly from within JProfiler.

    In the attach dialogs where you can attach to a JVM for profiling, you alternatively start JFR recording. This includes all remote connection capabilities of JProfiler, such as Windows services, SSH connections, Docker containers and Kubernetes.

    ScreenshotScreenshot

    Even if you are not interested in any particular JFR data, this recording mode can be useful if you are trying to obtain information about a production environment where a native profiling agent that uses the JVMTI may not be loaded. JFR snapshots can contain data about the runtime characteristics and even allow you to detect a pronounced CPU hot spot.

    This is similar to the adjacent "Heap dump only" option that takes an HPROF memory snapshot without loading the profiling agent.

    When you start JFR recording, a wizard is shown that lets you choose the JFR recording settings.

    ScreenshotScreenshot

    To avoid that the JFR recording fills up your entire hard disk, a maximum snapshot size has to be set. If exceeded, old chunks of data are discarded.

    JFR configurations files are located in the "lib/jfr" directory of the JRE. They contain a high-level configuration scheme that is shown as a UI by JProfiler on the same wizard step.

    In the next step of the wizard, the result of this configuration is shown as a tree of all JFR events. If you have already profiled this JRE before, JProfiler will offer you to use the last settings.

    ScreenshotScreenshot

    After recording is started, the JFR recording button changes to show "Stop JFR". Also, the background color of the unselected JVM entry in the table changes to show that a JProfiler JFR recording is running.

    ScreenshotScreenshot

    After clicking "Stop JFR", the JFR snapshot is transmitted to the local machine and opened in JProfiler. These snapshots are temporary. If you want to keep the snapshot for later analysis, you can save them with the "Save snapshot" action.

    ScreenshotScreenshot

    If a JVM where you have started a JFR recording in JProfiler terminates before you open it, the attach dialog will have a "Terminated JFR" entry for it, and you can use it to download the JFR snapshot that the JVM saved at exit.

    ScreenshotScreenshot

    If JFR recordings are running in a JVM that were not started by JProfiler, you can still open them in JProfiler. In that case, JProfiler will not show the recording wizard when you click the "Start JFR" button but a dialog where you can choose whether to start a new recording or open an existing JFR recording. Existing recordings will never be stopped by JProfiler.

    ScreenshotScreenshot

    The probe events view has been improved in many ways. This view is part of nearly all probes.

    Many probes handle a number of different event types at the same time. The type selector above the events table now allows you to select multiple event types. For example, in the "Sockets" probe, you can now analyze when sockets were opened and closed without getting distracted by the intervening "Read" and "Write" events.

    ScreenshotScreenshot

    When you select multiple events, the stack trace view at the bottom now shows cumulated data. For example, you can see the CPU hot spots of the selected events with backtraces.

    ScreenshotScreenshot

    The other available views are the "probe hot spots with backtraces" that have the payload at the top and the "probe call tree".

    ScreenshotScreenshot

    Scales for durations and throughputs can now be adjusted in the view settings dialog of the probe events view and the control objects view. These settings are saved separately for each probe.

    ScreenshotScreenshot

    Filtering in the probe events and the control objects views now works on a per-column basis. You can add multiple filters at the same time, either at the top of the table or most conveniently from the context menu, in order to use a value in the selected row. Filters are added as tag labels above the table and can be removed individually by closing them.

    ScreenshotScreenshot

    The probe events view now includes a histogram view for event durations and optionally a histogram view for throughputs if the probe measures memory. By default, the views are logarithmic, so you can easily spot outliers. By selecting a value range on the horizontal axis, you can add a filter for the probe events table.

    ScreenshotScreenshot

    You can now filter probe events by selecting a time range in the probe telemetry views. You can do that either by dragging the mouse or by using one of the selection actions in the context menu.

    ScreenshotScreenshot

    Probe event filters can now be set from the probe call tree and the probe hot spots view. The context menu in both tree views as well as the tool bar has an action to create a filter and switch to the probe events view.

    ScreenshotScreenshot

    Multiple control objects can now be selected and the associated events can be shown. This allows you to analyze events for an entire category of control objects.

    ScreenshotScreenshot

    VM telemetries have been improved.

    You can now drag and drop VM telemetries in the overview to change their order. This is useful to compare telemetries of interest. The change in the order is persistent across profiling sessions and is reflected in the view selector on the left.

    Also, the telemetries from the recorded object views are now always visible, even if no allocations are recorded. In that case, you will see an inline recording button that lets you conveniently start allocation recording. The context menu also includes the recording action if you want to stop it again that way as well as other actions to show the recorded objects view or the full telemetry.

    ScreenshotScreenshot

    Probe telemetries can be added to the VM telemetries section. Previously, you had to activate a probe and navigate to its telemetry view to see one of its telemetries. This made it difficult to compare them with the system telemetries or with telemetries from other probes. Now you can configure a session to include any number of probe telemetries directly in the VM telemetries section.

    ScreenshotScreenshot

    In the probe telemetry registry dialog, all available probe telemetries are listed and you can select multiple telemetries at once.

    ScreenshotScreenshot

    The probe telemetries are added at the bottom, but can be dragged to the desired index in the VM telemetries overview. Like the telemetries from the recording actions, probe telemetries have an inline recording button if recording is currently stopped, and the context menu allows you to navigate to the probe view.

    ScreenshotScreenshot

    In the full probe telemetries, you can select a time range to create a filter in the probe events view, just like in the probe view itself. After such a selection, the probe events view will be shown.

    ScreenshotScreenshot

    Telemetries that show rates are now shown as histograms. For example, this includes the recorded throughputs in the "Files" probe. Previously, these telemetries were shown as line graphs which did not give a sense of the total throughputs when looking at time periods much larger than a minute.

    ScreenshotScreenshot

    Finally, any telemetry can now be exported as SVG. The bitmap export is optionally still supported.

    ScreenshotScreenshot

    The current locking graph and current monitors views have been improved. These views are principally used for analyzing deadlocks.

    Current monitor data is now a snapshot rather than continuously updated. This makes it easier to analyze a single locking situation. There is an action in the toolbar to dump the current monitors.

    ScreenshotScreenshot

    The current monitor snapshot also makes it possible to save this information in a JProfiler snapshot or to time the monitor snapshot programmatically. There is a new method in the controller API as well as a trigger action for this purpose.

    ScreenshotScreenshot

    Current monitors and current locking graph views now show java.util.concurrent locks. In attach mode, these views are now available, but only for java.util.concurrent locks.

    Current monitors and locking graph views now group similar threads. This makes it easier to interpret locking situations with many threads and is important for supporting virtual threads where large numbers of threads may be active at the same time.

    ScreenshotScreenshot

    The thread history view and the probe timeline views now support reordering. You can drag threads or control objects to their desired location or use the sorting drop-down to order the view by start time, by name or by thread group.

    ScreenshotScreenshot

    Flame graphs have been improved. Flame graphs are available in call tree views from the "Analyze->Show Call Tree" action.

    When inspecting the nodes in the flame graph by hovering over them with the mouse, the tooltip can get in the way and obscure part of the flame graph that you might want to look at. Now you can use the pin button in the top-right corner of the tooltip to move the tooltip to a fixed location with the gripper at the top. The pin button then becomes a close button.

    ScreenshotScreenshot

    A "Show Source and a "Show Bytecode" action have been added to the context menu in the flame graph. As all such actions in JProfiler, the "Show Source" action will open the source file in the IDE if you are using an IDE integration.

    ScreenshotScreenshot

    Flame graph colorizations are now persisted, so you don't have to configure them each time again for new profiling sessions.

    Finally, flame graphs can now be exported as SVG. The exported SVG has basic tooltips so you can see the method names and their times.

    ScreenshotScreenshot

    An action to modify the session classpath has been added to all script editors. Many features in JProfiler allow you to enter a script for various purposes. For example, the "Split method with a script" action is available in the context menu of the call tree view. If the class of the method or a class of a parameter is not in the configured session classpath, JProfiler cannot provide code completion or compile a script that uses its members.

    To solve this problem conveniently, JProfiler now adds action labels to modify the session classpath right next to the missing classes in the script header. After adding the relevant JAR files to the classpath, you will be able to use the classes in the script immediately.

    ScreenshotScreenshot

    Attach mode was improved.

    In the list of attachable JVMs, JProfiler now shows the JRE path when no other naming information about the application is available. Because many applications use a private JRE, this makes it possible to identify those applications.

    On Linux, you can now attach to processes that were started by systemd with "PrivateTmp=yes" in the systemd unit file. You have to use the root user to attach to such processes.

    Also on Linux, JProfiler now inspects the mounts that were namespaced per-process to find writable directories. This affects daemons launched by systemd with "ProtectSystem=strict" in their system unit file, for example.

    Added support for Linux Alpine ARM.

    JVMs on this architecture can now be profiled by JProfiler.

      JProfiler 13.02022-01-31change log

      Support for attaching to JVMs running in a Kubernetes cluster has been added. The attach window now offers three main modes: Besides the existing radio buttons for JVMs running on the local machine and a remote machine there is now a Kubernetes cluster option.

      JProfiler uses the "kubectl" command line utility which can be available locally or on a remote machine via SSH.

      ScreenshotScreenshot

      After clicking on "Start", you can select a container in a tree of Kubernetes namespaces and pods.

      ScreenshotScreenshot

      JProfiler assumes that kubectl is already configured to connect to your cluster. If special command line options are required, they can be configured at the top of the dialog and can be made persistent on request.

      ScreenshotScreenshot

      After selecting the container, you can select from all JVMs that are running in the container. Should you need to switch to another container in your Kubernetes cluster, you can do so with the "Select Container" action.

      ScreenshotScreenshot

      If you choose to execute kubectl locally, the location of kubectl is detected automatically and can be adjusted in the general settings if required.

      ScreenshotScreenshot

      JProfiler can now attach to JVMs running in Docker Desktop on Windows and macOS and on local Docker installations on Linux. Previously, only Docker on remote Linux hosts was supported.

      To attach to a Docker container that is running locally, go to the "Quick attach" dialog, select the "On this computer" section and click on the "Select Container" link.

      ScreenshotScreenshot

      After selecting the container, the list of JVMs that are running in the container will be shown and you can proceed just like when attaching to a JVM that is running directly on the local machine.

      ScreenshotScreenshot

      As shown above, the selection dialog may contain locally running Kubernetes containers. You can also use the Kubernetes attach instead of the Docker attach in this case. Instead of generated names starting with "k8s", the local Kubernetes attach will show more informative container names.

      ScreenshotScreenshot

      Support for attaching to OpenJ9 JVMs has been added. It requires a recent OpenJ9 JVM (8u281+, 11.0.11+ or Java 17+) or an IBM JVM that is based on such a release.

      Previously, the only way to profile OpenJ9 and IBM JVMs was to add the -agentpath VM parameter at startup.

      ScreenshotScreenshot

      This is especially important for profiling OpenJ9 and IBM JVMs running in containers where attach mode is the only way to profile without undesirable modifications of the container. For example, you can now attach to the Websphere Liberty Docker container without any further configuration.

      ScreenshotScreenshot

      Attach functionality has been improved in several ways:

      • A user switcher has been added on Linux to profile JVMs started by different users
      • Support has been added for attaching to JVMs running in Redhat UBI-minimal images
      • FreeBSD and AIX are now supported target platforms for the remote attach functionality
      • On Windows it is now possible to attach to a JVM started by the same user but running in a different session
      • Elevated users can now attach to JVMs started by any user with jpenable on Windows when the PID is provided as long as the JProfiler installation is readable for that user
      • Different temporary directory settings for JProfiler and the profiled JVM no longer prevent attaching on Windows when a PID is provided for jpenable
      ScreenshotScreenshot

      OpenWebStart can now be profiled by JProfiler. After the discontinuation of Java Web Start in Java 11, OpenWebStart has been developed as a drop-in open source reimplementation based on IcedTea-Web by RedHat.

      JProfiler now offers a Web Start session type where the only thing that you have to configure is the JNLP URL in order to start profiling.

      ScreenshotScreenshot

      All JNLP URLs that have already been executed by OpenWebStart are shown in the chooser dialog.

      ScreenshotScreenshot

      A sunburst diagram visualization has been added to the biggest objects view of the heap walker. By default, the biggest objects view continues to show the tree view, but you can change the display with the view mode chooser at the top.

      The diagram is composed of a series of concentric segmented rings and shows the entire content of the dominator tree up to a maximum depth in one single image. References originate in the innermost ring and propagate towards the outer rim of the circle.

      This visualization gives you a flattened perspective with high information density that allows you to discover reference patterns and see large primitive and object arrays at a glance through their special color coding.

      ScreenshotScreenshot

      Clicking on any ring segment sets a new root for the circle, thereby expanding the maximum depth that you can see in the diagram. Clicking on the hollow center of the diagram restores the previous root.

      ScreenshotScreenshot

      More information about instances and their immediately retained objects is displayed on the right side of the diagram when you hover over them with the mouse. When the mouse is outside any ring segment, the list on the right side shows the biggest objects in the innermost ring.

      ScreenshotScreenshot

      Hovering over the list of biggest objects on the right highlights the corresponding ring segments and clicking on a list item sets a new root for the diagram. To create a new object set, you can choose from the actions in the context menu, both on the ring segments as well as on the list items.

      ScreenshotScreenshot

      As for the tree view mode, you can group the analysis by class loaders. The class loaders will be shown in the innermost ring.

      ScreenshotScreenshot

      An additional grouping mode that can also be combined with class loader grouping is grouping by classes. If selected, all biggest objects of a particular class at the same reference level are combined into a single node.

      ScreenshotScreenshot

      The Reactor Netty web client is now supported for the HTTP client probe.

      This goes together with support for the Spring WebFlux HTTP client that uses Reactor Netty under the hood by default. The Spring WebFlux HTTP client is also supported with the Apache HTTP client.

      ScreenshotScreenshot

      In addition to the HTTP client probe, the support for the Reactor Netty and Spring WebFlux HTTP clients is important for HTTP tracking where HTTP call sites are annotated with hyperlinks in the call tree view.

      ScreenshotScreenshot

      If the server JVM is profiled at the same time in a different JProfiler window, clicking on the hyperlink will show the execution site in that window. Remote request tracking not only works with live sessions, but also with snapshots.

      ScreenshotScreenshot

      The JEE/Spring aggregation level provides a high-level view for the call tree where only Spring beans and JEE components like servlets or EJBs are shown. All classes that have been annotated by @Component or any derived annotation like @Service or @Repository are detected as Spring beans.

      ScreenshotScreenshot

      JEE and Spring bean nodes are explained in the tree legend dialog that is available from the tool bar in all views that show a call tree.

      ScreenshotScreenshot

      This aggregation level is especially useful for the hotspots view, where it shows hot spots that are determined not on a per-method basis but on a per-bean basis. All details of the operations that are performed in other classes and library calls are included in the Spring bean nodes.

      ScreenshotScreenshot

      Aggregation levels can not only be selected in call tree views, but also in allocation and probe views.

      ScreenshotScreenshot

      JProfiler now supports live switching between light and dark mode. When the OS theme changes, JProfiler will switch automatically. In the general settings, it is also possible to select a fixed theme.

      ScreenshotScreenshot

      Probes in JProfiler now support the following recent releases:

      • Hibernate 6
      • RestEasy 6
      • Ktor 2
      • MariaDB connector 3

      The documentation is now available in dark mode. The default theme follows the OS theme and can be switched manually in the top right corner.

      Screenshot
        JProfiler 12.02020-11-23change log

        Flame graphs have been added. All views that show call trees can alternatively be shown as flame graphs that show the entire content of a call tree in one image. Calls originate at the bottom of the flame graph and propagate towards the top.

        Screenshot

        Flame graphs are implemented as a call tree analysis and are nested below the current call tree view. By selecting a node in the call tree, you can set the initial root node for the flame graph.

        Screenshot

        Child nodes are sorted alphabetically and are centered on their parent node. Due to the self-time that is spent in each node, the "flames" get progressively more narrow toward the top. More information about nodes is displayed in the tool tip.

        Screenshot

        Flame graphs have a very high information density. You can zoom in on areas of interest, or set a new root node by double-clicking on it. When changing roots multiple times in a row, you can move back again in the history of roots.

        Screenshot

        Another way to analyze flame graphs is to add colorizations based on class names, package names or arbitrary search terms. The first matching colorization is used for each node.

        Screenshot

        Colorizations can be conveniently added and removed from the context menu.

        Screenshot

        In addition to colorizations, you can use the quick search functionality to find nodes of interest. With the cursor keys you can cycle through match results while the tooltip is being displayed for the currently highlighted match.

        Screenshot

        Flame graphs are not only available for top-level call tree views but also for the results of other call tree analyses, such as "Collapsed recursions".

        Screenshot

        Support for Netty has been added. The previous "Servlet" probe and the Netty functionality were merged into the new "HTTP Server" probe.

        If you are running a Netty-based web server like Spring Reactor, Vertx or Ktor, the HTTP Server probe shows you the intercepted URLs with invocation counts and well as their total and average processing times.

        Screenshot

        The events view of the HTTP Server probe can list the single URL interceptions chronologically.

        Screenshot

        Just like for Servlet containers, the call tree is split for each URL, so you can see associated subtree separately.

        Screenshot

        To determine the granularity of the split as well as the displayed URL, the probe settings of the HTTP server probe now offer generic splitting scripts in addition to the Servlet scripts.

        Screenshot

        Unlike for Servlet scripts that offer the HttpRequest object from the Servlet API as a parameter, the Netty landscape is less stable with several incompatible APIs. This is why JProfiler offers an HttpRequest parameter from its own API to provide access to common request properties. Advanced use cases can get the underlying Netty request object via the getRequestObject() method.

        Screenshot

        As with Servlet scripts, you can configure a list of scripts to create multiple nested splitting levels in the call tree. Several script templates for common tasks are available.

        Screenshot

        Netty is mostly used for async handling of HTTP requests. Because of the associated thread changes, the subtree below an URL in the call tree will not show the entire handling of the request.

        With the async request tracking functionality in JProfiler, you can follow the entire execution flow. Most frameworks, like Spring Reactor use executors for async handling, so the "Executors" request tracking type has to be activated. If you are using a server based on Kotlin Coroutines like Ktor, then "Kotlin Coroutines" is the required tracking type.

        Screenshot

        If async tracking is used, the call tree view will suggest to inline async executions both on top of the view as well as on the call sites where the async calls are initiated.

        Screenshot

        The result of the "Inline async executions" analysis then contains a single call tree across all involved threads that show you the entire handling of a particular request URL, cumulated for all matching requests.

        Screenshot

        Attaching to JVMs running in Docker containers is now supported in the SSH remote attach functionality.

        You start out by using the quick attach functionality with an SSH tunnel to a remote Linux machine.

        Screenshot

        Initially, the JVM processes running directly on the remote machine are listed. At the top of the remote attach dialog is a line that shows the currently selected remote Docker container.

        Screenshot

        With the Switch container hyperlink you can then choose a running Docker container.

        Screenshot

        After selecting a Docker container, all JVMs that are running in it are shown. JProfiler will then use Docker commands to automatically install the profiling agent in the selected container, prepare the JVM for profiling and tunnel the profiling protocol to the outside.

        Screenshot

        If the SSH login user is not in the docker group, you can switch the remote user first.

        Screenshot

        Attach functionality has been improved in several ways.

        JVMs that have been started with the "-agentpath" VM parameter for profiling are now shown in the attach dialog, both for local and remote attach. These JVMs are waiting at startup for a connection from the JProfiler GUI. In that state, the normal attach mechanism in the JVM is not yet available, so an alternative attach mechanism had to be implemented.

        Screenshot

        Previously, when connecting to a remote machine, a JRE had to be available for the login user, or the connection would fail. Starting with this release, a message is shown in the JVM list with a hyperlink to manually enter a path to a JRE. This allows you to switch to a user that may have access to a JRE or switch to a Docker container that contains a JRE.

        Screenshot

        Previously, when changing the user on the remote machine, no HPROF snapshots could be taken. In this release, a method to transfer the heap dump data between accounts has been implemented and the "Heap dump only" action is now enabled.

        Screenshot

        An inspection to group classes by their class loader has been added to the heap walker. This inspection groups java.lang.Class objects and is complementary to the existing inspection that can group instances by their class loader.

        The result of the inspection can either include classes whose java.lang.Class objects are contained in the current object set or classes that have instances in the current object set.

        Screenshot

        When you select a class loader in the grouping table at the top, the corresponding java.lang.Class objects are shown in in the data views below.

        Screenshot

        Jakarta EE 9 is now supported. Jakarta EE 9 switches the packages for the API from javax.* to jakarta.*. JProfiler now supports both the old as well as the new packages for the "HTTP server" probe.

        When writing URL splitting scripts in the JProfiler UI, a javax.servlet.http.HttpServletRequest request object is available as a parameter. If the profiled container supports Jakarta EE 9, calls into the servlet API are transparently translated into the jakarta.servlet. namespace.

        Screenshot

        The NetBeans plugin has been improved. An action has been added to attach to a running JVM. This is especially important for profiling Maven projects that do not use the exec plugin as well as Gradle projects where the JProfiler plugin has no way to insert VM parameters into the Java invocation.

        Screenshot

        A preference page has been added where you can adjust the JProfiler executable as well as the window policy for opening new profiling sessions. All other settings continue to be available the session startup dialog and are saved separately for each NetBeans project.

        Screenshot

        JProfiler has a new cross-platform light mode. This the new light look and feel from the IntelliJ IDEA platform.

        Screenshot

        A localization into simplified Chinese has been added. If the locale of your machine is "zh_CN", the installer will pick it up automatically, otherwise you can switch languages in the general settings dialog.

        Screenshot

        Support for profiling on Alpine Linux has been added. Alpine Linux is especially popular for Docker because of its smaller image size. It uses a different C standard library than other Linux distributions, so the native profiling agent needs a separate port.

        Starting with this release, the musl-x64 architecture is included in JProfiler.

        Support for profiling on macOS ARM has been added. While profiling JVMs compiled for the x86 architecture is possible on new ARM-based macOS machines via Rosetta, new JVMs compiled directly for the new ARM architecture require a different native profiling agent.

        Starting with this release, the macOS profiling agent is a universal binary that contains implementations for both x64 and ARM64.

        At the time of the 12.0 release, JProfiler is not bundled with an ARM JRE yet, so the JProfiler GUI will run via Rosetta on macOS ARM machines. A release that includes an ARM JRE is expected shortly as corresponding JREs become available.

          JProfiler 11.12020-01-08change log

          An async sampling mode without safe-point bias has been added on macOS and Linux. It uses the non-standard AsyncGetCallTrace API in the HotSpot JVM to get call stacks at arbitrary times and not only at certain execution states that the JVM considers as safe points. This profiling mode produces more accurate CPU data for highly multi-threaded CPU-bound code.

          Screenshot

          The only thread state that can be measured in this way is "Running". The waiting, blocking and net I/O thread states are not available. Contrary to the other method call recording types that use a "Runnable" thread state to measure when threads are eligible to be scheduled on the CPU, "Running" only measures times where a thread is actually scheduled on the CPU. Obtaining the call stack can fail for a number of reasons which are summarized in the "Sampling misses" top-level node.

          Screenshot

          Async sampling uses pre-allocated buffers that may be too small to capture all call stacks. This condition is also shown in the call tree, and the session settings offer a way to increase the buffer size relative to the default size.

          Note that Windows does not have signal handlers and does not support this kind of data collection.

          Native sampling has been added on macOS and Linux. When using the new async sampling mode described above, you can optionally enable native sampling. If native sampling is enabled, JProfiler resolves symbols in native libraries and adds native nodes to the call tree.

          Screenshot

          In native call tree nodes, the associated native library is shown in square brackets followed by the function name.

          Screenshot

          In the classes aggregation mode, native libraries are grouped together, while in the package aggregation level all native calls are cumulated. When removing parts of the call tree, the library also acts like a class, so by removing the class of the selected node (a new feature in this release that is presented below), the entire native library is removed from the call tree.

          Screenshot

          JProfiler can now open JDK flight recorder (JFR) snapshots. JFR snapshots are often recorded in production environments where the installation of profiling agents is restricted. Starting with this release, you can now bring JProfiler's full arsenal of analytic features into play when analyzing these snapshots.

          The available views in the view selector are different from those in a regular JProfiler sessions. JProfiler can construct a number of telemetry views from JFR event data including heap size, recorded throughput, GC activity, class loading, thread counts and CPU load.

          Screenshot

          In the memory section, both heap statistics and allocation recording are shown. If heap statistics were enabled for JFR recording, the "Live Objects" view shows the classes that took up most of the heap. The difference between the first and the last heap statistics is shown in the "Difference" column.

          Data from allocation recording in JFR snapshots maps to the "Recorded objects", "Allocation Call Tree" and "Allocation Hot Spots" views.

          Screenshot

          In the CPU section, "Call tree", "Hot Spots" and "Call Graph" views are available. JFR recording truncates traces depending on buffer sizes, those traces are contained in a separate top-level node.

          JFR recording only records threads that are runnable and in Java code. Due to the nature of JFR sampling, no time calculation is possible and only event counts are displayed. The "Waiting", "Blocking" and "Socket and file I/O" thread states show times because they are assembled from timed events.

          Screenshot

          JFR snapshots contain thread data that JProfiler uses to build the thread history view. The contained thread dumps are also displayed in JProfiler.

          Screenshot

          "Waiting", "Blocking" and "Parking" events from JFR snapshots are shown in the "Monitor History" view in the "Monitors & Locks" section. These events are the sources of the "Waiting" and "Blocked" thread states in the CPU views. The "Monitor Usage Statistics" view is also available.

          Screenshot

          Finally, a number of probes are built from JFR events: "Classes", "Files", "Sockets" and "Exceptions". These views show data depending on whether the corresponding JFR events were recorded. The "Files" and "Sockets" probes are also the source of the "Socket and file IO" thread state in the CPU views.

          Screenshot

          The new outlier detection view shows how the invocation times of methods vary with respect to their average. Data for this view is always available when instrumentation is used for method call recording and CPU recording is active. It replaces the "Method statistics" view which had a separate recording that added a lot of overhead.

          Screenshot

          The outlier coefficient quantifies how much the maximum invocation times deviates from the average. Methods with a high outlier coefficient are good candidates for inspection with the exceptional method run recording feature in JProfiler that shows you their slowest invocations separately in the call tree. Also, time measurements for outlier detection are performed for the same selected thread state as for exceptional method run recording.

          From the outlier detection view, you can easily select a method as an exceptional method in the context menu.

          Screenshot

          Thresholds for maximum times and invocation counts limit the amount of displayed data and can be adjusted in the view settings.

          Screenshot

          Tracking of async calls now works with sampling, including the new async sampling mode. Previously, you had to profile with instrumentation to use the "Inline async executions" call tree analysis. Having to change the profiling mode to get inlined call stacks proved limiting, particularly for Kotlin coroutines, where inlining is especially important.

          Screenshot

          In the call tree you can now show all threads that contribute to the selected call stack. When looking at the call tree cumulated for all threads, it can be interesting to know which single threads are responsible for adding time to the selected node. The context menu gives you access to this action.

          Screenshot

          From the list of threads you can directly switch to a selected thread in the call tree.

          Screenshot

          Call tree removal for entire classes or packages has been implemented. You can remove parts of the call tree by selecting a node and choosing the "Remove selected subtree" action.

          Screenshot

          In addition to just removing the selected method, you can now choose to remove all invocations of the selected class or the selected package.

          Screenshot

          In some situations, you may want to keep the selected method, but just set its self-time to zero. For example, this can be the case for the Thread.run top-level method where most of its self-time is in non-profiled classes and you want the percentages of the profiled code to add up to 100%.

          Screenshot

          Telemetry drawing has been improved. When telemetries are zoomed out they now show the minimum and maximum envelopes of jittery graphs instead of the interpolated average for each pixel. Also, peaks are preserved for all zoom levels.

          Screenshot

          In addition, you can now zoom in and out with CTRL + scroll wheel or pinch gestures on macOS, and telemetries will preserve the current cursor position when zoom levels are changed.

            JProfiler 11.02019-03-19change log

            An HTTP probe for outgoing requests has been added. Both synchronous and asynchronous calls are measured. The supported HTTP clients are:

            • java.net.URLConnection
            • Java HTTP Client (Java 11+)
            • Apache HttpClient 4.x
            • Apache Async HttpClient 4.x
            • OkHttp 3.9+
            • Jersey (JAX-RS) Async Client 2.x
            • RestEasy Async Client 3.x
            • CXF Async Client 3.1.1+
            Screenshot
            You can choose whether to include the consumption of the request body in the time measurement or stop timing when the response code is available. This setting can be changed on the fly.
            Screenshot

            As with other probes, you can optionally annotate HTTP requests into the call tree view. By default, the description of the HTTP request is the URL without the query, with an option to retain the full URL for the probe events view. Optionally, you can configure a script that constructs a description for the HTTP request which may be important to get useful hot spots.

            Screenshot

            HTTP calls can now be tracked between JVMs. When using a supported HTTP client and a servlet container on the server side, call sites and execution sites are navigable in both directions.

            Screenshot

            Call sites get a special icon and a hyperlink that shows the execution site in the server JVM that must be profiled and open in a separate window for the navigation to work.

            Screenshot

            Execution sites are recorded separately for each call site so you can analyze different types of requests in isolation. Each execution site is represented by a special node that is inserted into the call tree.

            Screenshot

            Async executions can be inlined. Both call tree and hot spots views now have an "Inline Async executions" call tree analysis for this purpose. If async tracking is active, a status display above the call tree provides easy access to the action that creates the inlined view. Also, nodes in the call tree where an async call was intercepted have a corresponding hyperlink.

            Screenshot

            In the call tree analysis, "async execution" nodes show the call tree from the execution sites. By default, the time below async nodes is not added to the parent nodes in the tree to show the non-blocking nature of the calls.

            Screenshot

            You can also choose to add the times as though the calls were blocking. This is useful for analyzing which call stacks cause most time to be spent in the async execution sites.

            Screenshot

            When async tracking is not activated, JProfiler detects which async tracking types have occurred in the JVM and presents them to you in the status bar. With a single click you can then activate tracking.

            Screenshot

            To quickly see which async tracking types are activated, hover the mouse over the status bar icon and click it to invoke the configuration dialog.

            Screenshot

            If async calls originate in unprofiled call stacks, they are not recorded by default in order to avoid cluttering the analysis with framework internals. If such filtered async calls are detected, the async status bar offers actions to switch on recording for these calls.

            Screenshot

            Support for tracking Kotlin Coroutines has been added. Coroutines are the basis for asynchronous programming with Kotlin in a multi-platform way. Without dedicated tool support, a call tree involving coroutines is highly segmented and a lot of information about causality is lost.

            Screenshot

            When the tracking of Kotlin Coroutines is activated, the "Inline Async executions" call tree analysis produces a call tree that shows call stacks across suspension boundaries. If applied to the hot spots view, the call tree analysis shows you backtraces that would otherwise terminate at the first suspended method call.

            Screenshot

            Kotlin Coroutine tracking also measures the times when coroutines are suspended and shows these times in separate nodes in the inline call tree. This is needed to determine how long coroutine execution takes in total. If only the actual processing times of coroutines are of interest, suspended times can be hidden.

            Screenshot

            JProfiler has new light and dark look and feels. The look and feels are based on the IntelliJ IDEA Darcula look and feel and its light derivative. These look and feels support HiDPI on Windows, Linux and macOS. On Windows and macOS, JProfiler is bundled with the "JetBrains Runtime" OpenJDK that has better HiDPI support than the default JDK.

            Screenshot

            The default setting for the look and feel is now "Automatic", which chooses the dark theme if the OS is in dark mode and the light theme otherwise. This detection is currently implemented on macOS 10.14+ and Windows 10 build 1809+.

            Screenshot

            A non-interactive mode for jpcontroller has been added. jpcontroller is a command line executable for controlling recording and saving snapshots. In addition to the existing interactive mode, you can now also automate profiling sessions without the need for manual input.

            For an automated invocation, you pass [pid | host:port] to select a profiled JVM as well as the --non-interactive argument. A list of commands is read, either from stdin, or from a command file that is specified with the --command-file argument.

            Commands for this non-interactive mode are the same as the method names in the JProfiler MBean. They require the same number of parameters, separated by spaces. In addition, a sleep <seconds> command is provided.

            For example, a command sequence could look like this:

            addBookmark "Hello world"
            startCPURecording true
            sleep 10
            stopCPURecording
            saveSnapshot /path/to/snapshot.jps

            Automatic detection of call tree filters for IDE integrations. For new sessions, the IDE integrations for IntelliJ IDEA, eclipse, and NetBeans now scan the source packages of the profiled project and set inclusive filters accordingly. Inclusive filters yield much better results than the default exclusive filters.

            If all packages with editable source files have a common prefix package, that package will be used, otherwise all top-level packages that contain classes will be added separately.

            This detection will only be performed the first time a project is profiled, and any manual changes in the call tree filter settings will not be lost. On the "Define filters" tab of the session settings dialog, you can force this calculation to be repeated with the reset button.

            Screenshot

            Sampling for allocation recording reduces the high overhead of allocation recording considerably. By default, every 10th allocation is recorded which roughly reduces the overhead to 1/10th compared to recording all allocations.

            Screenshot

            For live sessions, the sampling rate can be adjusted on the fly without losing any data.

            Screenshot

            Session settings have been improved. The previously separate "Profiling settings" dialog has been integrated into the new session settings dialog.

            You can now easily copy selected parts of other sessions into the current session configuration.

            Screenshot

            There is now a default session that you can configure from the general settings dialog. All new sessions start out with these defaults.

            Screenshot

            In the default session, you can now disable the initial question for new sessions whether sampling or instrumentation should be used.

            Screenshot

            If you connect to a JVM is already profiled with different session settings, JProfiler will give you the option to keep the previous session settings. These previous settings can be inspected in the session settings dialog after the profiling session has been started. This mechanism eliminates time-consuming class retransformations.

            Screenshot

            Applying profiling settings at startup without using the JProfiler UI has been made more convenient. When using the "id" or "config" options in the -agentpath VM parameter, you no longer have to specify the "nowait" option which is now implied. The "id" option is no longer necessary if the config file only contains a single session. A typical VM parameter for profiling will now look like this:

            -agentpath:/opt/jprofiler/bin/linux-x64/libjprofilerti.so=config=~/jprofiler_config.xml

            The ~ character is now replaced with the home directory on all platforms, and the default name of the JProfiler config file has been changed to jprofiler_config.xml in order to make it less generic.

            When configuring profiling sessions on remote machines or offline profiling sessions without the JProfiler UI, it is sometimes necessary to inspect the config file and make manual changes. In this release, the config file format has been improved making it less verbose by omitting default settings and making all aspects of the configuration easily understandable.

            Floating licenses now work over SSH. Customers with floating licenses can now configure an SSH connection to the floating license server using the same configuration as for SSH connections to profiled JVMs.

            Screenshot

            A tabular display of char and byte arrays has been added in the outgoing reference view of the heap walker. Larger amounts of data can now be interpreted much more easily.

            In addition, char arrays now show their string value right next to the instance.

            Screenshot

            Shortened package names in call trees have been implemented. This optional setting is configurable in the view settings dialog.

            Screenshot

            For code bases with deep package structures, the shortened package names reduce the amount of displayed text and make it easier to focus on class and method names.

            Screenshot

            Improved support for IBM and OpenJ9 JVMs. This release brings feature parity with HotSpot JVMs in a number of areas:

            • Support for primitive data in the heap walker
            • All inspections in the heap walker are now supported
            • File and process probes are supported for IBM 8+ JVMs
            • The "Save HPROF snapshot" UI action and "Create an HPROF heap dump" trigger action now generate PHD dumps

            Support for profiling Java 12+. Also, all OpenJDK variants are now supported when starting sessions from the JProfiler UI.