1 /*
   2  * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.jfr.cmd;
  27 
  28 import java.nio.file.Files;
  29 import java.nio.file.Path;
  30 import java.util.Arrays;
  31 import java.util.regex.Matcher;
  32 import java.util.regex.Pattern;
  33 
  34 import jdk.jfr.Configuration;
  35 import jdk.jfr.Event;
  36 import jdk.jfr.Recording;
  37 import jdk.testlibrary.OutputAnalyzer;
  38 import jdk.testlibrary.ProcessTools;;
  39 
  40 final class ExecuteHelper {
  41 
  42     public static Object[] array;
  43 
  44     static class CustomEvent extends Event {
  45         int intValue;
  46         long longValue;
  47         double doubliValue;
  48         float floatValue;
  49         String stringValue;
  50         Short shortValue;
  51         boolean booleanValue;
  52         char charValue;
  53         double trickyDouble;
  54     }
  55 
  56     public static OutputAnalyzer run(String... args) {
  57         String[] array = new String[args.length + 1];
  58         System.arraycopy(args, 0, array, 1, args.length);
  59         array[0] = "jdk.jfr.internal.cmd.Execute";
  60         try {
  61             return ProcessTools.executeTestJava(array);
  62         } catch (Exception e) {
  63             String message = String.format("Caught exception while executing '%s'", Arrays.asList(array));
  64             throw new RuntimeException(message, e);
  65         }
  66     }
  67 
  68     public static void emitCustomEvents() {
  69         // Custom events with potentially tricky values
  70         CustomEvent event1 = new CustomEvent();
  71         event1.trickyDouble = Double.NaN;
  72         event1.intValue = Integer.MIN_VALUE;
  73         event1.longValue = Long.MIN_VALUE;
  74         event1.doubliValue = Double.MIN_VALUE;
  75         event1.floatValue = Float.MIN_VALUE;
  76         StringBuilder sb = new StringBuilder();
  77         for (int i = 0; i < 512; i++) {
  78             sb.append((char) i);
  79         }
  80         sb.append("\u2324");
  81         event1.stringValue = sb.toString();
  82         event1.shortValue = Short.MIN_VALUE;
  83         event1.booleanValue = true;
  84         event1.booleanValue = false;
  85         event1.charValue = '\b';
  86         event1.commit();
  87 
  88         CustomEvent event2 = new CustomEvent();
  89         event2.trickyDouble = Double.NEGATIVE_INFINITY;
  90         event2.intValue = Integer.MAX_VALUE;
  91         event2.longValue = Long.MAX_VALUE;
  92         event2.doubliValue = Double.MAX_VALUE;
  93         event2.floatValue = Float.MAX_VALUE;
  94         event2.stringValue = null;
  95         event2.shortValue = Short.MAX_VALUE;
  96         event2.booleanValue = false;
  97         event2.charValue = 0;
  98         event2.commit();
  99     }
 100 
 101     public static Path createProfilingRecording() throws Exception {
 102         Path file = Files.createTempFile("recording", ".jfr");
 103         // Create a recording with some data
 104         try (Recording r = new Recording(Configuration.getConfiguration("profile"))) {
 105             r.start();
 106 
 107             // Allocation event
 108             array = new Object[1000000];
 109             array = null;
 110 
 111             // Class loading event etc
 112             provokeClassLoading();
 113 
 114             // GC events
 115             System.gc();
 116 
 117             // ExecutionSample
 118             long t = System.currentTimeMillis();
 119             while (System.currentTimeMillis() - t < 50) {
 120                 // do nothing
 121             }
 122 
 123             // Other periodic events, i.e CPU load
 124             Thread.sleep(1000);
 125 
 126             r.stop();
 127             r.dump(file);
 128         }
 129 
 130         return file;
 131     }
 132 
 133     private static void provokeClassLoading() {
 134        // Matching a string with regexp
 135        // is expected to load some classes and generate some VM events
 136        Pattern p = Pattern.compile("a*b");
 137        Matcher m = p.matcher("aaaaab");
 138        m.matches();
 139     }
 140 }