src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java
changeset 50745 a390cbb82d47
parent 50226 408021edf22f
child 50881 a21cad3fa448
equal deleted inserted replaced
50744:6c306d54366d 50745:a390cbb82d47
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 package jdk.jfr.internal.dcmd;
    25 package jdk.jfr.internal.dcmd;
    26 
    26 
    27 import java.io.IOException;
    27 import java.io.IOException;
       
    28 import java.nio.file.Files;
    28 import java.nio.file.InvalidPathException;
    29 import java.nio.file.InvalidPathException;
       
    30 import java.nio.file.Path;
    29 import java.nio.file.Paths;
    31 import java.nio.file.Paths;
    30 import java.text.ParseException;
    32 import java.text.ParseException;
    31 import java.time.Duration;
    33 import java.time.Duration;
       
    34 import java.util.Arrays;
    32 import java.util.HashMap;
    35 import java.util.HashMap;
    33 import java.util.Map;
    36 import java.util.Map;
    34 
    37 
    35 import jdk.jfr.FlightRecorder;
    38 import jdk.jfr.FlightRecorder;
    36 import jdk.jfr.Recording;
    39 import jdk.jfr.Recording;
    37 import jdk.jfr.internal.JVM;
    40 import jdk.jfr.internal.JVM;
       
    41 import jdk.jfr.internal.LogLevel;
       
    42 import jdk.jfr.internal.LogTag;
       
    43 import jdk.jfr.internal.Logger;
       
    44 import jdk.jfr.internal.OldObjectSample;
       
    45 import jdk.jfr.internal.PrivateAccess;
    38 import jdk.jfr.internal.SecuritySupport.SafePath;
    46 import jdk.jfr.internal.SecuritySupport.SafePath;
    39 import jdk.jfr.internal.Type;
    47 import jdk.jfr.internal.Type;
    40 import jdk.jfr.internal.Utils;
       
    41 import jdk.jfr.internal.jfc.JFC;
    48 import jdk.jfr.internal.jfc.JFC;
    42 
    49 
    43 /**
    50 /**
    44  * JFR.start
    51  * JFR.start
    45  *
    52  *
    49 
    56 
    50     /**
    57     /**
    51      * Execute JFR.start.
    58      * Execute JFR.start.
    52      *
    59      *
    53      * @param name optional name that can be used to identify recording.
    60      * @param name optional name that can be used to identify recording.
    54      * @param configurations names of settings files to use, i.e. "default" or
    61      * @param settings names of settings files to use, i.e. "default" or
    55      *        "default.jfc".
    62      *        "default.jfc".
    56      * @param delay delay before recording is started, in nanoseconds. Must be
    63      * @param delay delay before recording is started, in nanoseconds. Must be
    57      *        at least 1 second.
    64      *        at least 1 second.
    58      * @param duration duration of the recording, in nanoseconds. Must be at
    65      * @param duration duration of the recording, in nanoseconds. Must be at
    59      *        least 1 second.
    66      *        least 1 second.
    71      * @return result output
    78      * @return result output
    72      *
    79      *
    73      * @throws DCmdException if recording could not be started
    80      * @throws DCmdException if recording could not be started
    74      */
    81      */
    75     @SuppressWarnings("resource")
    82     @SuppressWarnings("resource")
    76     public String execute(String name, String[] configurations, Long delay, Long duration, Boolean disk, String path, Long maxAge, Long maxSize, Boolean dumpOnExit, Boolean pathToGcRoots) throws DCmdException {
    83     public String execute(String name, String[] settings, Long delay, Long duration, Boolean disk, String path, Long maxAge, Long maxSize, Boolean dumpOnExit, Boolean pathToGcRoots) throws DCmdException {
       
    84         if (LogTag.JFR_DCMD.shouldLog(LogLevel.DEBUG)) {
       
    85             Logger.log(LogTag.JFR_DCMD, LogLevel.DEBUG, "Executing DCmdStart: name=" + name +
       
    86                     ", settings=" + Arrays.asList(settings) +
       
    87                     ", delay=" + delay +
       
    88                     ", duration=" + duration +
       
    89                     ", disk=" + disk+
       
    90                     ", filename=" + path +
       
    91                     ", maxage=" + maxAge +
       
    92                     ", maxsize=" + maxSize +
       
    93                     ", dumponexit =" + dumpOnExit +
       
    94                     ", path-to-gc-roots=" + pathToGcRoots);
       
    95         }
    77         if (name != null) {
    96         if (name != null) {
    78             try {
    97             try {
    79                 Integer.parseInt(name);
    98                 Integer.parseInt(name);
    80                 throw new DCmdException("Name of recording can't be numeric");
    99                 throw new DCmdException("Name of recording can't be numeric");
    81             } catch (NumberFormatException nfe) {
   100             } catch (NumberFormatException nfe) {
    84         }
   103         }
    85 
   104 
    86         if (duration == null && Boolean.FALSE.equals(dumpOnExit) && path != null) {
   105         if (duration == null && Boolean.FALSE.equals(dumpOnExit) && path != null) {
    87             throw new DCmdException("Filename can only be set for a time bound recording or if dumponexit=true. Set duration/dumponexit or omit filename.");
   106             throw new DCmdException("Filename can only be set for a time bound recording or if dumponexit=true. Set duration/dumponexit or omit filename.");
    88         }
   107         }
    89         if (dumpOnExit == null && path != null) {
   108 
    90             dumpOnExit = Boolean.TRUE;
       
    91         }
       
    92 
   109 
    93         Map<String, String> s = new HashMap<>();
   110         Map<String, String> s = new HashMap<>();
    94 
   111 
    95         if (configurations == null || configurations.length == 0) {
   112         if (settings == null || settings.length == 0) {
    96             configurations = new String[] { "default" };
   113             settings = new String[] { "default" };
    97         }
   114         }
    98 
   115 
    99         for (String configName : configurations) {
   116         for (String configName : settings) {
   100             try {
   117             try {
   101                 s.putAll(JFC.createKnown(configName).getSettings());
   118                 s.putAll(JFC.createKnown(configName).getSettings());
   102             } catch (IOException | ParseException e) {
   119             } catch (IOException | ParseException e) {
   103                 throw new DCmdException("Could not parse setting " + configurations[0], e);
   120                 throw new DCmdException("Could not parse setting " + settings[0], e);
   104             }
   121             }
   105         }
   122         }
   106 
   123 
   107         Utils.updateSettingPathToGcRoots(s, pathToGcRoots);
   124         OldObjectSample.updateSettingPathToGcRoots(s, pathToGcRoots);
   108 
   125 
   109         if (duration != null) {
   126         if (duration != null) {
   110             if (duration < 1000L * 1000L * 1000L) {
   127             if (duration < 1000L * 1000L * 1000L) {
   111                 // to avoid typo, duration below 1s makes no sense
   128                 // to avoid typo, duration below 1s makes no sense
   112                 throw new DCmdException("Could not start recording, duration must be at least 1 second.");
   129                 throw new DCmdException("Could not start recording, duration must be at least 1 second.");
   131 
   148 
   132         if (disk != null) {
   149         if (disk != null) {
   133             recording.setToDisk(disk.booleanValue());
   150             recording.setToDisk(disk.booleanValue());
   134         }
   151         }
   135         recording.setSettings(s);
   152         recording.setSettings(s);
       
   153         SafePath safePath = null;
   136 
   154 
   137         if (path != null) {
   155         if (path != null) {
   138             try {
   156             try {
   139                 recording.setDestination(Paths.get(path));
   157                 if (dumpOnExit == null) {
       
   158                     // default to dumponexit=true if user specified filename
       
   159                     dumpOnExit = Boolean.TRUE;
       
   160                 }
       
   161                 Path p = Paths.get(path);
       
   162                 if (Files.isDirectory(p) && Boolean.TRUE.equals(dumpOnExit)) {
       
   163                     // Decide destination filename at dump time
       
   164                     // Purposely avoid generating filename in Recording#setDestination due to
       
   165                     // security concerns
       
   166                     PrivateAccess.getInstance().getPlatformRecording(recording).setDumpOnExitDirectory(new SafePath(p));
       
   167                 } else {
       
   168                     safePath = resolvePath(recording, path);
       
   169                     recording.setDestination(safePath.toPath());
       
   170                 }
   140             } catch (IOException | InvalidPathException e) {
   171             } catch (IOException | InvalidPathException e) {
   141                 recording.close();
   172                 recording.close();
   142                 throw new DCmdException("Could not start recording, not able to write to file %s. %s ", path, e.getMessage());
   173                 throw new DCmdException("Could not start recording, not able to write to file %s. %s ", path, e.getMessage());
   143             }
   174             }
   144         }
   175         }
   173         if (recording.isToDisk() && duration == null && maxAge == null && maxSize == null) {
   204         if (recording.isToDisk() && duration == null && maxAge == null && maxSize == null) {
   174             print(" No limit specified, using maxsize=250MB as default.");
   205             print(" No limit specified, using maxsize=250MB as default.");
   175             recording.setMaxSize(250*1024L*1024L);
   206             recording.setMaxSize(250*1024L*1024L);
   176         }
   207         }
   177 
   208 
   178         if (path != null && duration != null) {
   209         if (safePath != null && duration != null) {
   179             println(" The result will be written to:");
   210             println(" The result will be written to:");
   180             println();
   211             println();
   181             printPath(new SafePath(path));
   212             printPath(safePath);
   182         } else {
   213         } else {
   183             println();
   214             println();
   184             println();
   215             println();
   185             String cmd = duration == null ? "dump" : "stop";
   216             String cmd = duration == null ? "dump" : "stop";
   186             String fileOption = path == null ? "filename=FILEPATH " : "";
   217             String fileOption = path == null ? "filename=FILEPATH " : "";