From 377fc8bdf8c78f0fd0bb00ffb3b07989d5d90aac Mon Sep 17 00:00:00 2001 From: Jason Feng Date: Wed, 5 Feb 2025 12:38:23 -0500 Subject: [PATCH] JFR dump to Jcmd current working directory by default If the filename supplied is not an absolute path, Jcmd current work directory is used instead of the target VM location; Throw an error if the duration option doesn't have any time unit. Signed-off-by: Jason Feng --- .../tools/attach/target/DiagnosticUtils.java | 61 +++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/DiagnosticUtils.java b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/DiagnosticUtils.java index 70a06f9f163..5e120d8379f 100644 --- a/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/DiagnosticUtils.java +++ b/jcl/src/java.base/share/classes/openj9/internal/tools/attach/target/DiagnosticUtils.java @@ -23,8 +23,12 @@ package openj9.internal.tools.attach.target; +import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -144,6 +148,9 @@ public class DiagnosticUtils { private static final String DIAGNOSTICS_JFR_START = "JFR.start"; private static final String DIAGNOSTICS_JFR_DUMP = "JFR.dump"; private static final String DIAGNOSTICS_JFR_STOP = "JFR.stop"; + + private static final int ERROR_NO_TIME_UNIT = -1; + private static final int ERROR_NO_TIME_DURATION = -2; /*[ENDIF] JFR_SUPPORT */ /** @@ -209,7 +216,39 @@ public static String makeThreadPrintCommand(boolean lockedSynchronizers) { * @return formatted string */ public static String makeJcmdCommand(String[] options, int skip) { - String cmd = String.join(DIAGNOSTICS_OPTION_SEPARATOR, Arrays.asList(options).subList(skip, options.length)); + int optionsLength = options.length; + /*[IF JFR_SUPPORT]*/ + if (optionsLength >= 2) { + // there is a jcmd command + if (DIAGNOSTICS_JFR_START.equalsIgnoreCase(options[1])) { + // search JFR.start options + for (int i = 2; i < optionsLength; i++) { + String option = options[i]; + IPC.logMessage("makeJcmdCommand: option = ", option); + if (option.startsWith("filename=")) { + String fileName = option.substring(option.indexOf("=") + 1); + try { + Path filePath = Paths.get(fileName); + if (!filePath.isAbsolute()) { + // default recording file path is jcmd current working directory + String jcmdPWD = Paths.get("").toAbsolutePath().toString(); + fileName = jcmdPWD + File.separator + fileName; + IPC.logMessage("makeJcmdCommand: absolute filename = ", fileName); + // replace existing entry with an absolute jcmd pwd path for the target VM + options[i] = "filename=" + fileName; + } + } catch (InvalidPathException ipe) { + // ignore this exception and keep the original entry + IPC.logMessage("makeJcmdCommand: ipe = ", ipe.getMessage()); + } + // only one filename is allowed + break; + } + } + } + } + /*[ENDIF] JFR_SUPPORT */ + String cmd = String.join(DIAGNOSTICS_OPTION_SEPARATOR, Arrays.asList(options).subList(skip, optionsLength)); return cmd; } @@ -415,13 +454,25 @@ private static long convertToMilliseconds(String timeValue) { timeInMilli = TimeUnit.DAYS.toMillis(time); break; default: - // no unit or unrecognized unit, assume milliseconds - timeInMilli = time; + // no unit or unrecognized unit, return ERROR_NO_TIME_UNIT + timeInMilli = ERROR_NO_TIME_UNIT; break; } return timeInMilli; } + /** + * Parse a time parameter, and return the duration in milliseconds. + * If the time unit is missing, ERROR_NO_TIME_UNIT is returned. + * If the paramName is not in parameters, ERROR_NO_TIME_DURATION is returned. + * + * @param paramName the parameter name + * @param parameters the parameter array + * + * @return the duration in milliseconds, + * ERROR_NO_TIME_UNIT if no time unit, + * ERROR_NO_TIME_DURATION if paramName wasn't found. + */ private static long parseTimeParameter(String paramName, String[] parameters) { for (String param : parameters) { if (param.startsWith(paramName + "=")) { @@ -431,7 +482,7 @@ private static long parseTimeParameter(String paramName, String[] parameters) { } } } - return -1; + return ERROR_NO_TIME_DURATION; } private static String parseStringParameter(String paramName, String[] parameters, String defaultValue) { @@ -488,6 +539,8 @@ public void run() { } }; timer.schedule(jfrDumpTask, duration); + } if (duration == ERROR_NO_TIME_UNIT) { + return DiagnosticProperties.makeErrorProperties("The duration doesn't have a time unit."); } else { // the recording is on until JFR.stop }