test/jdk/jdk/jfr/jcmd/TestJcmdDump.java
changeset 50745 a390cbb82d47
parent 50113 caf115bb98ad
child 51214 67736b4846a0
equal deleted inserted replaced
50744:6c306d54366d 50745:a390cbb82d47
    24  */
    24  */
    25 
    25 
    26 package jdk.jfr.jcmd;
    26 package jdk.jfr.jcmd;
    27 
    27 
    28 import java.io.File;
    28 import java.io.File;
       
    29 import java.nio.file.Files;
       
    30 import java.util.ArrayList;
       
    31 import java.util.List;
       
    32 import java.util.function.Predicate;
    29 
    33 
    30 import jdk.test.lib.jfr.FileHelper;
    34 import jdk.jfr.Event;
       
    35 import jdk.jfr.Recording;
       
    36 import jdk.jfr.consumer.RecordedEvent;
       
    37 import jdk.jfr.consumer.RecordingFile;
       
    38 import jdk.test.lib.jfr.EventNames;
    31 import jdk.test.lib.process.OutputAnalyzer;
    39 import jdk.test.lib.process.OutputAnalyzer;
    32 
    40 
    33 /*
    41 /*
    34  * @test
    42  * @test
    35  * @summary The test verifies JFR.dump command
    43  * @summary The test verifies JFR.dump command
    36  * @key jfr
    44  * @key jfr
    37  * @library /test/lib /test/jdk
    45  * @library /test/lib /test/jdk
    38  * @run main/othervm jdk.jfr.jcmd.TestJcmdDump
    46  * @run main/othervm -XX:FlightRecorderOptions:maxchunksize=1M jdk.jfr.jcmd.TestJcmdDump
    39  */
    47  */
    40 public class TestJcmdDump {
    48 public class TestJcmdDump {
    41 
    49 
       
    50     static class StoppedEvent extends Event {
       
    51     }
       
    52     static class RunningEvent extends Event {
       
    53     }
       
    54 
       
    55     private static final String[] names = { null, "r1" };
       
    56     private static final boolean booleanValues[] = { true, false };
       
    57 
    42     public static void main(String[] args) throws Exception {
    58     public static void main(String[] args) throws Exception {
    43         String name = "TestJcmdDump";
       
    44         File recording = new File(name + ".jfr");
       
    45 
    59 
       
    60         // Create a stopped recording in the repository to complicate things
       
    61         Recording r = new Recording();
       
    62         r.start();
       
    63         StoppedEvent de = new StoppedEvent();
       
    64         de.commit();
       
    65         r.stop();
    46 
    66 
    47         OutputAnalyzer output = JcmdHelper.jcmd("JFR.start", "name=" + name);
    67         // The implementation of JFR.dump touch code that can't be executed using the
    48         JcmdAsserts.assertRecordingHasStarted(output);
    68         // Java API. It is therefore important to try all combinations. The
    49         JcmdHelper.waitUntilRunning(name);
    69         // implementation is non-trivial and depends on the combination
       
    70         for (String name : names) {
       
    71             for (boolean disk : booleanValues) {
       
    72                 try (Recording r1 = new Recording(); Recording r2 = new Recording()) {
       
    73                     System.out.println();
       
    74                     System.out.println();
       
    75                     System.out.println("Starting recordings with disk=" + disk);
       
    76                     r1.setToDisk(disk);
       
    77                     // To complicate things, only enable OldObjectSample for one recording
       
    78                     r1.enable(EventNames.OldObjectSample).withoutStackTrace();
       
    79                     r1.setName("r1");
       
    80                     r2.setToDisk(disk);
       
    81                     r2.setName("r2");
       
    82                     r1.start();
       
    83                     r2.start();
    50 
    84 
    51         output = JcmdHelper.jcmd("JFR.dump",
    85                     // Expect no path to GC roots
    52                 "name=" + name,
    86                     jfrDump(Boolean.FALSE, name, disk, rootCount -> rootCount == 0);
    53                 "filename=" + recording.getAbsolutePath());
    87                     // Expect path to GC roots
    54         JcmdAsserts.assertRecordingDumpedToFile(output, name, recording);
    88                     jfrDump(null, name, disk, rootCount -> rootCount == 0);
    55         JcmdHelper.stopAndCheck(name);
    89                     // Expect at least one path to a GC root
    56         FileHelper.verifyRecording(recording);
    90                     jfrDump(Boolean.TRUE, name, disk, rootCount -> rootCount > 0);
       
    91                 }
       
    92             }
       
    93         }
       
    94         r.close(); // release recording data from the stopped recording
       
    95     }
       
    96 
       
    97     private static void jfrDump(Boolean pathToGCRoots, String name, boolean disk, Predicate<Integer> successPredicate) throws Exception {
       
    98         List<Object> leakList = new ArrayList<>();
       
    99         leakList.add(new Object[1000_0000]);
       
   100         System.gc();
       
   101         while (true) {
       
   102             RunningEvent re = new RunningEvent();
       
   103             re.commit();
       
   104             leakList.add(new Object[1000_0000]);
       
   105             leakList.add(new Object[1000_0000]);
       
   106             leakList.add(new Object[1000_0000]);
       
   107             System.gc(); // This will shorten time for object to be emitted.
       
   108             File recording = new File("TestJCMdDump.jfr");
       
   109             String[] params = buildParameters(pathToGCRoots, name, recording);
       
   110             OutputAnalyzer output = JcmdHelper.jcmd(params);
       
   111             JcmdAsserts.assertRecordingDumpedToFile(output, recording);
       
   112             int rootCount = 0;
       
   113             int oldObjectCount = 0;
       
   114             int stoppedEventCount = 0;
       
   115             int runningEventCount = 0;
       
   116             for (RecordedEvent e : RecordingFile.readAllEvents(recording.toPath())) {
       
   117                 if (e.getEventType().getName().equals(EventNames.OldObjectSample)) {
       
   118                     if (e.getValue("root") != null) {
       
   119                         rootCount++;
       
   120                     }
       
   121                     oldObjectCount++;
       
   122                 }
       
   123                 if (e.getEventType().getName().equals(StoppedEvent.class.getName())) {
       
   124                     stoppedEventCount++;
       
   125                 }
       
   126                 if (e.getEventType().getName().equals(RunningEvent.class.getName())) {
       
   127                     runningEventCount++;
       
   128                 }
       
   129             }
       
   130             System.out.println("Name: " + name);
       
   131             System.out.println("Disk: " + disk);
       
   132             System.out.println("Path to GC roots: " + pathToGCRoots);
       
   133             System.out.println("Old Objects: " + oldObjectCount);
       
   134             System.out.println("Root objects: "+ rootCount);
       
   135             System.out.println("Stopped events: "+ stoppedEventCount);
       
   136             System.out.println("Running events: "+ runningEventCount);
       
   137 
       
   138             System.out.println();
       
   139             if (runningEventCount == 0) {
       
   140                 throw new Exception("Missing event from running recording");
       
   141             }
       
   142             if (name == null && stoppedEventCount == 0) {
       
   143                 throw new Exception("Missing event from stopped recording");
       
   144             }
       
   145             if (name != null && stoppedEventCount > 0) {
       
   146                 throw new Exception("Stopped event should not be part of dump");
       
   147             }
       
   148             if (oldObjectCount != 0 && successPredicate.test(rootCount)) {
       
   149                 return;
       
   150             }
       
   151             System.out.println();
       
   152             System.out.println();
       
   153             System.out.println();
       
   154             System.out.println("************* Retrying! **************");
       
   155             Files.delete(recording.toPath());
       
   156         }
       
   157     }
       
   158 
       
   159     private static String[] buildParameters(Boolean pathToGCRoots, String name, File recording) {
       
   160         List<String> params = new ArrayList<>();
       
   161         params.add("JFR.dump");
       
   162         params.add("filename=" + recording.getAbsolutePath());
       
   163         if (pathToGCRoots != null) { // if path-to-gc-roots is omitted, default is used (disabled).
       
   164             params.add("path-to-gc-roots=" + pathToGCRoots);
       
   165         }
       
   166         if (name != null) { // if name is omitted, all recordings will be dumped
       
   167             params.add("name=" + name);
       
   168         }
       
   169         return params.toArray(new String[0]);
    57     }
   170     }
    58 }
   171 }