Skip to content

Commit

Permalink
Introduce --enable-monitoring option.
Browse files Browse the repository at this point in the history
  • Loading branch information
fniephaus committed Aug 22, 2022
1 parent 432065a commit 8e6bbfd
Show file tree
Hide file tree
Showing 17 changed files with 308 additions and 127 deletions.
1 change: 1 addition & 0 deletions docs/reference-manual/native-image/BuildOptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The following options are supported across both GraalVM Community and Enterprise
* `--enable-https`: enable HTTPS support in a native executable
* `--enable-preview`: allow classes to depend on preview features of this release
* `--enable-url-protocols`: list comma-separated URL protocols to enable
* `--enable-monitoring`: enable monitoring features that allow the VM to be inspected at run time. Comma-separated list can contain 'heapdump', 'jfr', 'jvmstat', or 'all'. For example: `--enable-monitoring=heapdump,jvmstat`.
* `--features`: a comma-separated list of fully qualified [Feature implementation classes](https://www.graalvm.org/sdk/javadoc/index.html?org/graalvm/nativeimage/hosted/Feature.html)
* `--force-fallback`: force building of a fallback native executable
* `--gc=<value>`: select Native Image garbage collector implementation. Allowed options for `<value>` are: `G1` for G1 garbage collector (**GraalVM Enterprise only**); `epsilon` for Epsilon garbage collector; `serial` for Serial garbage collector (default).
Expand Down
4 changes: 2 additions & 2 deletions docs/reference-manual/native-image/JFR.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ To record JFR events when running a native executable, JFR support and JFR recor

To build a native executable with the JFR events support, you first need to include JFR at build time, then enable the system, start a recording, and configure logging at native executable run time.

To build a native executable with JFR, use the `-H:+AllowVMInspection` flag:
To build a native executable with JFR, use the `--enable-monitoring=jfr` flag:
```shell
native-image -H:+AllowVMInspection JavaApplication
native-image --enable-monitoring=jfr JavaApplication
```
To enable the system, start a recording, and configure logging at run time, the following options are supported:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@ GraalVM Native Image supports JFR events and users can use [`jdk.jfr.Event`](htt

To record JFR events when running a native executable, JFR support and JFR recording must be enabled, and this guide covers how to do that.

> Note: JFR events recording is not supported on GraalVM distribution for Windows. JFR is only supported with native executables built on GraalVM JDK 11.
> Note: JFR events recording is not supported on GraalVM JDK for Windows. JFR is only supported with native executables built on GraalVM JDK 11.
## Enable JFR Support and Record Events at Run Time

To build a native executable with the JFR events support, you first need to include JFR at build time, then enable the system, start a recording, and configure logging at native executable run time.
The following options are supported:
* `-H:+AllowVMInspection`: enable the VM inspection
* `-XX:+FlightRecorder`: use to enable JFR
To build a native executable with the JFR events support, you first need to add the `--enable-monitoring=jfr` option when invoking the `native-image` tool. Then enable the system, start a recording, and configure logging at native executable run time:
* `-XX:+FlightRecorder`: use to enable JFR at run time
* `-XX:StartFlightRecording`: use to start a recording on application's startup
* `-XX:FlightRecorderLogging`: use to configure the log output for the JFR system

Expand Down Expand Up @@ -61,9 +59,9 @@ Follow the steps below to practice building a native executable with JFR support

3. Build a native executable with the VM inspection enabled:
```shell
$JAVA_HOME/bin/native-image -H:+AllowVMInspection JFRDemo
$JAVA_HOME/bin/native-image --enable-monitoring=jfr JFRDemo
```
The `-H:+AllowVMInspection` option enables features such as JFR that can be used to inspect the VM.
The `--enable-monitoring=jfr` option enables features such as JFR that can be used to inspect the VM.

4. Run the executable and start recording:
```shell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,42 @@ permalink: /reference-manual/native-image/guides/create-heap-dump/

You can create a heap dump of a running executable to monitor its execution. Just like any other Java heap dump, it can be opened with the [VisualVM](../../../tools/visualvm.md) tool.

To enable heap dump support, native executables must be built with the `-H:+AllowVMInspection` option. Heap dumps can then be created in three different ways:
To enable heap dump support, native executables must be built with the `--enable-monitoring=heapdump` option. Heap dumps can then be created in three different ways:

1. Dump the initial heap of a native executable using the `-XX:+DumpHeapAndExit` command-line option.
2. Create heap dumps sending `USR1` (other supported signals are `QUIT/BREAK` for stack dumps and `USR2` to dump runtime compilation information).
3. Create a heap dumps programmatically through the [`org.graalvm.nativeimage.VMRuntime#dumpHeap`](https://github.com/oracle/graal/blob/master/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VMInspection.java) API.
1. Create heap dumps with VisualVM.
2. Dump the initial heap of a native executable using the `-XX:+DumpHeapAndExit` command-line option.
3. Create heap dumps sending a `SIGUSR1` signal at run time.
4. Create heap dumps programmatically using the [`org.graalvm.nativeimage.VMRuntime#dumpHeap`](https://github.com/oracle/graal/blob/master/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VMInspection.java) API.

All three approaches are described below.

>Note: Creating heap dumps is not available on the Microsoft Windows platform.
## Create Heap Dumps with VisualVM

A convenient way to create heap dumps is to use [VisualVM](../../../tools/visualvm.md).
For this, you need to add `jvmstat` to the `--enable-monitoring` option (for example, `--enable-monitoring=heapdump,jvmstat`).
This will allow VisualVM to pick up and list running Native Image processes.
You can then request heap dumps in the same way you can request them when your application runs on the JVM (for example, right-click on the process, then select "Heap Dump").

## Dump the Initial Heap of a Native Executable

Use the `-XX:+DumpHeapAndExit` command-line option to dump the initial heap of a native executable.
This can be useful to identify which objects the Native Image build process allocated to the executable's heap.
For a HelloWorld example, use the option as follows:

```shell
$GRAALVM_HOME/bin/native-image HelloWorld -H:+AllowVMInspection
$GRAALVM_HOME/bin/native-image HelloWorld --enable-monitoring=heapdump
./helloworld -XX:+DumpHeapAndExit
Heap dump created at '/path/to/helloworld.hprof'.
```

## Handle USR1 Signals
## Create Heap Dumps with SIGUSR1 (Linux/macOS only)

The following example is a simple multi-threaded Java application that runs for 60 seconds.
This provides you with enough time to send it a `USR1` signal. The application will handle the signal and create a heap dump in the application's working directory. The heap dump will contain the `Collection` of `Person`s referenced by the static variable `CROWD`.
This provides you with enough time to send it a `SIGUSR1` signal. The application will handle the signal and create a heap dump in the application's working directory. The heap dump will contain the `Collection` of `Person`s referenced by the static variable `CROWD`.

Follow these steps to build a native executable that will produce a heap dump when it receives a `USR1` signal.
Follow these steps to build a native executable that will produce a heap dump when it receives a `SIGUSR1` signal.

1. Save the following code in a file named _SVMHeapDump.java_:
```java
Expand Down Expand Up @@ -122,11 +130,11 @@ Follow these steps to build a native executable that will produce a heap dump wh
```shell
$JAVA_HOME/bin/javac SVMHeapDump.java
```
Build a native executable using the `-H:+AllowVMInspection` command-line option.
(This causes the resulting native executable to produce a heap dump when it receives a `USR1` signal.)
Build a native executable using the `--enable-monitoring=heapdump` command-line option.
(This causes the resulting native executable to produce a heap dump when it receives a `SIGUSR1` signal.)

```shell
$JAVA_HOME/bin/native-image SVMHeapDump -H:+AllowVMInspection
$JAVA_HOME/bin/native-image SVMHeapDump --enable-monitoring=heapdump
```

(The `native-image` builder creates a native executable from the `SVMHeapDump.class`.
Expand Down
9 changes: 3 additions & 6 deletions docs/tools/visualvm.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,9 @@ To capture a heap dump of, for example, a Ruby application for later analysis, s
Then right-click its process in VisualVM and invoke the Heap Dump action.
A new heap viewer for the Ruby process opens.

__Note:__ [Native Image](../reference-manual/native-image/README.md) does not implement the JVMTI agent, so triggering heap dump creation from the Applications area is impossible.
Apply the `-H:+AllowVMInspection` flag with the `native-image` tool for native image processes.
This way your application will handle signals and capture a heap dump when it receives the SIGUSR1 signal.
The guest language REPL process must be started also with the `--jvm` flag to monitor it using VisualVM.
This functionality is available with [GraalVM Enterprise Edition](https://www.oracle.com/downloads/graalvm-downloads.html).
It is not available in GraalVM Community Edition.
__Note:__ Heap dump support must be explicitly enabled when using [Native Image](../reference-manual/native-image/README.md).
Add the `--enable-monitoring=heapdump,jvmstat` option when invoking the `native-image` tool to enable the heap dump feature and allow VisualVM to detect native executables via `jvmstat`.
This way your application will handle signals and capture a heap dump when it receives the `SIGUSR1` signal.
See the [Generating Native Heap Dumps](../reference-manual/native-image/guides/create-heap-dump-from-native-executable.md) page for details on capturing heap dumps from a native image process.

### Analyzing Objects
Expand Down
3 changes: 2 additions & 1 deletion sdk/mx.sdk/mx_sdk_vm_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,8 @@ def contents(self):
if isinstance(image_config, mx_sdk.LauncherConfig) or (isinstance(image_config, mx_sdk.LanguageLibraryConfig) and image_config.launchers):
build_args += [
'--install-exit-handlers',
'-H:+AllowVMInspection',
'--enable-monitoring=all',
'-H:+DumpRuntimeCompilationOnSignal',
]

if isinstance(image_config, (mx_sdk.LauncherConfig, mx_sdk.LanguageLibraryConfig)):
Expand Down
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-40170) Add `--silent` option to silence the build output.
* (GR-39475) Add initial support for jvmstat.
* (GR-39563) Add support for JDK 19 and Project Loom Virtual Threads (JEP 425) for high-throughput lightweight concurrency. Enable on JDK 19 with `native-image --enable-preview`.
* (GR-40264) Add `--enable-monitoring=<all,heapdump,jfr,jvmstat>` option to enable fine-grained control over monitoring features enabled in native executables. `-H:±AllowVMInspection` is now deprecated and will be removed in a future release.

## Version 22.2.0
* (GR-20653) Re-enable the usage of all CPU features for JIT compilation on AMD64.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.hosted.Feature;

import com.oracle.svm.core.VMInspection;
import com.oracle.svm.core.VMInspectionOptions;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.annotate.TargetClass;
Expand Down Expand Up @@ -276,7 +276,7 @@ public void teardown() {
class PosixPerfMemoryFeature implements Feature {
@Override
public boolean isInConfiguration(IsInConfigurationAccess access) {
return VMInspection.isEnabled();
return VMInspectionOptions.hasJvmstatSupport();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import org.graalvm.nativeimage.ProcessProperties;
import org.graalvm.nativeimage.VMRuntime;
import org.graalvm.nativeimage.hosted.Feature;

import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.jdk.RuntimeSupport;
import com.oracle.svm.core.log.Log;

import sun.misc.Signal;
import sun.misc.SignalHandler;

@AutomaticFeature
public class DumpHeapOnSignalFeature implements Feature {

@Override
public boolean isInConfiguration(IsInConfigurationAccess access) {
return VMInspectionOptions.hasHeapDumpSupport();
}

@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
RuntimeSupport.getRuntimeSupport().addStartupHook(new DumpHeapStartupHook());
}
}

final class DumpHeapStartupHook implements RuntimeSupport.Hook {
@Override
public void execute(boolean isFirstIsolate) {
if (isFirstIsolate) {
DumpHeapReport.install();
}
}
}

class DumpHeapReport implements SignalHandler {
private static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("UTC");

static void install() {
Signal.handle(new Signal("USR1"), new DumpHeapReport());
}

@Override
public void handle(Signal arg0) {
DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
dateFormat.setTimeZone(UTC_TIMEZONE);
String heapDumpFileName = "svm-heapdump-" + ProcessProperties.getProcessID() + "-" + dateFormat.format(new Date()) + ".hprof";
try {
VMRuntime.dumpHeap(heapDumpFileName, true);
} catch (IOException e) {
Log.log().string("IOException during dumpHeap: ").string(e.getMessage()).newline();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platform.WINDOWS;
import org.graalvm.nativeimage.hosted.Feature;

import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.deopt.DeoptimizationSupport;
import com.oracle.svm.core.heap.VMOperationInfos;
import com.oracle.svm.core.jdk.RuntimeSupport;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.thread.JavaVMOperation;

import sun.misc.Signal;
import sun.misc.SignalHandler;

@AutomaticFeature
public class DumpRuntimeCompilationOnSignalFeature implements Feature {

@Override
public boolean isInConfiguration(IsInConfigurationAccess access) {
return VMInspectionOptions.DumpRuntimeCompilationOnSignal.getValue() && !Platform.includedIn(WINDOWS.class) && DeoptimizationSupport.enabled();
}

@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
RuntimeSupport.getRuntimeSupport().addStartupHook(new DumpRuntimeCompilationStartupHook());
}
}

final class DumpRuntimeCompilationStartupHook implements RuntimeSupport.Hook {
@Override
public void execute(boolean isFirstIsolate) {
if (isFirstIsolate) {
DumpRuntimeCompilation.install();
}
}
}

class DumpRuntimeCompilation implements SignalHandler {
static void install() {
Signal.handle(new Signal("USR2"), new DumpRuntimeCompilation());
}

@Override
public void handle(Signal arg0) {
DumpRuntimeCompiledMethodsOperation vmOp = new DumpRuntimeCompiledMethodsOperation();
vmOp.enqueue();
}

private static class DumpRuntimeCompiledMethodsOperation extends JavaVMOperation {
DumpRuntimeCompiledMethodsOperation() {
super(VMOperationInfos.get(DumpRuntimeCompiledMethodsOperation.class, "Dump runtime compiled methods", SystemEffect.SAFEPOINT));
}

@Override
protected void operate() {
Log log = Log.log();
SubstrateDiagnostics.dumpRuntimeCompilation(log);
log.flush();
}
}
}
Loading

0 comments on commit 8e6bbfd

Please sign in to comment.