Skip to content

Commit

Permalink
8326116: JFR: Add help option to -XX:StartFlightRecording
Browse files Browse the repository at this point in the history
Reviewed-by: mgronlun
  • Loading branch information
egahlin committed Apr 16, 2024
1 parent 941bee1 commit f7c8413
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 23 deletions.
13 changes: 11 additions & 2 deletions src/hotspot/share/jfr/dcmd/jfrDcmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ void JfrDCmd::execute(DCmdSource source, TRAPS) {
if (invalid_state(output(), THREAD)) {
return;
}
if (source == DCmd_Source_Internal && _args != nullptr && strcmp(_args, "help") == 0) {
print_java_help("printStartupHelp");
vm_exit(0);
}

static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;C)[Ljava/lang/String;";
JavaValue result(T_OBJECT);
JfrJavaArguments execute(&result, javaClass(), "execute", signature, CHECK);
Expand All @@ -241,15 +246,19 @@ void JfrDCmd::execute(DCmdSource source, TRAPS) {
handle_dcmd_result(output(), result.get_oop(), source, THREAD);
}

void JfrDCmd::print_help(const char* name) const {
void JfrDCmd::print_java_help(const char* help_method) const {
static const char signature[] = "()[Ljava/lang/String;";
JavaThread* thread = JavaThread::current();
JavaValue result(T_OBJECT);
JfrJavaArguments printHelp(&result, javaClass(), "printHelp", signature, thread);
JfrJavaArguments printHelp(&result, javaClass(), help_method, signature, thread);
invoke(printHelp, thread);
handle_dcmd_result(output(), result.get_oop(), DCmd_Source_MBean, thread);
}

void JfrDCmd::print_help(const char* name) const {
print_java_help("printHelp");
}

static void initialize_dummy_descriptors(GrowableArray<DCmdArgumentInfo*>* array) {
assert(array != nullptr, "invariant");
DCmdArgumentInfo * const dummy = new DCmdArgumentInfo(nullptr,
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/jfr/dcmd/jfrDcmds.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class JfrDCmd : public DCmd {
JfrDCmd(outputStream* output, bool heap, int num_arguments);
virtual const char* javaClass() const = 0;
void invoke(JfrJavaArguments& method, TRAPS) const;
void print_java_help(const char* help_method) const;
public:
virtual void execute(DCmdSource source, TRAPS);
virtual void print_help(const char* name) const;
Expand Down
68 changes: 47 additions & 21 deletions src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import jdk.jfr.internal.jfc.model.JFCModel;
import jdk.jfr.internal.jfc.model.JFCModelException;
import jdk.jfr.internal.jfc.model.XmlInput;
import jdk.jfr.internal.util.Utils;

/**
* JFR.start
Expand Down Expand Up @@ -317,11 +318,35 @@ private boolean hasJDKEvents(Map<String, String> settings) {
return false;
}

public String[] printStartupHelp() {
Map<String, String> parameters = Map.of(
"$SYNTAX", "-XX:StartFlightRecording:[options]",
"$SOURCE", "-XX:StartFlightRecording:",
"$DELIMITER", ",",
"$DELIMITER_NAME", "comma",
"$DIRECTORY", exampleDirectory(),
"$JFC_OPTIONS", jfcOptions()
);
return Utils.format(helpTemplate(), parameters).lines().toArray(String[]::new);
}

@Override
public String[] printHelp() {
Map<String, String> parameters = Map.of(
"$SYNTAX", "JFR.start [options]",
"$SOURCE", "$ jcmd <pid> JFR.start ",
"$DELIMITER", " ",
"$DELIMITER_NAME", "whitespace",
"$DIRECTORY", exampleDirectory(),
"$JFC_OPTIONS", jfcOptions()
);
return Utils.format(helpTemplate(), parameters).lines().toArray(String[]::new);
}

private static String helpTemplate() {
// 0123456789001234567890012345678900123456789001234567890012345678900123456789001234567890
return """
Syntax : JFR.start [options]
Syntax : $SYNTAX
Options:
Expand Down Expand Up @@ -352,8 +377,8 @@ Virtual Machine (JVM) shuts down. If set to 'true' and no value
generated from the PID and the current date in the specified
directory. (STRING, no default value)
Note: If a filename is given, '%%p' in the filename will be
replaced by the PID, and '%%t' will be replaced by the time in
Note: If a filename is given, '%p' in the filename will be
replaced by the PID, and '%t' will be replaced by the time in
'yyyy_MM_dd_HH_mm_ss' format.
maxage (Optional) Maximum time to keep the recorded data on disk. This
Expand Down Expand Up @@ -409,27 +434,28 @@ Virtual Machine (JVM) shuts down. If set to 'true' and no value
take precedence. The whitespace character can be omitted for timespan values,
i.e. 20s. For more information about the settings syntax, see Javadoc of the
jdk.jfr package.
%s
Options must be specified using the <key> or <key>=<value> syntax.
$JFC_OPTIONS
Options must be specified using the <key> or <key>=<value> syntax. Multiple
options are separated with a $DELIMITER_NAME.
Example usage:
$ jcmd <pid> JFR.start
$ jcmd <pid> JFR.start filename=dump.jfr
$ jcmd <pid> JFR.start filename=%s
$ jcmd <pid> JFR.start dumponexit=true
$ jcmd <pid> JFR.start maxage=1h maxsize=1000M
$ jcmd <pid> JFR.start settings=profile
$ jcmd <pid> JFR.start delay=5m settings=my.jfc
$ jcmd <pid> JFR.start gc=high method-profiling=high
$ jcmd <pid> JFR.start jdk.JavaMonitorEnter#threshold=1ms
$ jcmd <pid> JFR.start +HelloWorld#enabled=true +HelloWorld#stackTrace=true
$ jcmd <pid> JFR.start settings=user.jfc com.example.UserDefined#enabled=true
$ jcmd <pid> JFR.start settings=none +Hello#enabled=true
Note, if the default event settings are modified, overhead may exceed 1%%.
""".formatted(jfcOptions(), exampleDirectory()).lines().toArray(String[]::new);
$SOURCE
$SOURCEfilename=dump.jfr
$SOURCEfilename=$DIRECTORY
$SOURCEdumponexit=true
$SOURCEmaxage=1h$DELIMITERmaxsize=1000M
$SOURCEsettings=profile
$SOURCEdelay=5m$DELIMITERsettings=my.jfc
$SOURCEgc=high$DELIMITERmethod-profiling=high
$SOURCEjdk.JavaMonitorEnter#threshold=1ms
$SOURCE+HelloWorld#enabled=true$DELIMITER+HelloWorld#stackTrace=true
$SOURCEsettings=user.jfc$DELIMITERcom.example.UserDefined#enabled=true
$SOURCEsettings=none$DELIMITER+Hello#enabled=true
Note, if the default event settings are modified, overhead may exceed 1%.
""";
}

private static String jfcOptions() {
Expand Down
23 changes: 23 additions & 0 deletions src/jdk.jfr/share/classes/jdk/jfr/internal/util/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -445,4 +446,26 @@ public static String makeSimpleName(EventType type) {
public static String makeSimpleName(String qualified) {
return qualified.substring(qualified.lastIndexOf(".") + 1);
}

public static String format(String template, Map<String, String> parameters) {
StringBuilder sb = new StringBuilder(3 * template.length() / 2);
List<String> keys = new ArrayList<>(parameters.keySet());
// Sort so longest keys are checked first in case keys overlap.
keys.sort((a, b) -> b.length() - a.length());
for (int i = 0; i < template.length(); i++) {
int index = i;
for (int j = 0; j < keys.size(); j++) {
String key = keys.get(j);
if (template.startsWith(key, i)) {
sb.append(parameters.get(key));
i += key.length() - 1;
break;
}
}
if (i == index) {
sb.append(template.charAt(i));
}
}
return sb.toString();
}
}
47 changes: 47 additions & 0 deletions test/jdk/jdk/jfr/startupargs/TestStartHelp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2024, 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.
*
* 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 jdk.jfr.startupargs;

import jdk.jfr.Recording;
import jdk.test.lib.Asserts;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;

/**
* @test
* @key jfr
* @requires vm.hasJFR
* @library /test/lib /test/jdk
* @run main jdk.jfr.startupargs.TestStartHelp
*/
public class TestStartHelp {

public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder("-XX:StartFlightRecording:help");
OutputAnalyzer out = ProcessTools.executeProcess(pb);
out.shouldContain("Syntax : -XX:StartFlightRecording:[options]");
out.shouldContain("options are separated with a comma.");
out.shouldHaveExitValue(0);
}
}

1 comment on commit f7c8413

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.