1 /*
   2  * Copyright (c) 2018, 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.jvm;
  27 
  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.time.Duration;
  31 import java.util.ArrayList;
  32 import java.util.List;
  33 
  34 import jdk.jfr.AnnotationElement;
  35 import jdk.jfr.Event;
  36 import jdk.jfr.EventType;
  37 import jdk.jfr.FlightRecorder;
  38 import jdk.jfr.Recording;
  39 import jdk.jfr.ValueDescriptor;
  40 import jdk.jfr.consumer.RecordedEvent;
  41 import jdk.jfr.consumer.RecordingFile;
  42 
  43 /**
  44  * @test TestGetThreadId
  45  * @key jfr
  46  * 
  47  * @library /lib /
  48  * 
  49  * @run main/othervm jdk.jfr.jvm.TestJavaEvent
  50  */
  51 public class TestJavaEvent {
  52 
  53     private static final int EVENTS_PER_THREAD = 50;
  54     private static final int THREAD_COUNT = 100;
  55 
  56     public static class MyEvent extends Event {
  57         float floatValue;
  58         double doubleValue;
  59         int intValue;
  60         long longValue;
  61         char charValue;
  62         byte byteValue;
  63         String stringValue;
  64         Thread threadValue;
  65         Class<?> classValue;
  66 
  67         public void setFloatValue(float value) {
  68             floatValue = value;
  69         }
  70 
  71         public void setDoubleValue(double value) {
  72             doubleValue = value;
  73         }
  74 
  75         public void setIntValue(int value) {
  76             intValue = value;
  77         }
  78 
  79         public void setLongValue(long value) {
  80             longValue = value;
  81         }
  82 
  83         public void setCharValue(char value) {
  84             charValue = value;
  85         }
  86 
  87         public void setByteValue(byte value) {
  88             byteValue = value;
  89         }
  90 
  91         public void setStringValue(String value) {
  92             stringValue = value;
  93         }
  94 
  95         public void setThreadValue(Thread value) {
  96             threadValue = value;
  97         }
  98 
  99         public void setClassValue(Class<?> value) {
 100             classValue = value;
 101         }
 102     }
 103 
 104     public static void main(String... args) throws IOException, InterruptedException {
 105         Recording r = new Recording();
 106         r.enable(MyEvent.class).withThreshold(Duration.ofNanos(0)).withoutStackTrace();
 107         r.start();
 108         List<Thread> threads = new ArrayList<>();
 109         for (int n = 0; n < THREAD_COUNT; n++) {
 110             Thread t = new Thread(TestJavaEvent::emitEvents);
 111             threads.add(t);
 112             t.start();
 113         }
 114         for (Thread t : threads) {
 115             t.join();
 116         }
 117 
 118         r.stop();
 119         // prettyPrint();
 120         File file = File.createTempFile("test", ".jfr");
 121         r.dump(file.toPath());
 122         int eventCount = 0;
 123         for (RecordedEvent e : RecordingFile.readAllEvents(file.toPath())) {
 124             if (e.getEventType().getName().equals(MyEvent.class.getName())) {
 125                 eventCount++;
 126             }
 127             System.out.println(e);
 128         }
 129         System.out.println("Event count was " + eventCount + ", expected " + THREAD_COUNT * EVENTS_PER_THREAD);
 130         r.close();
 131     }
 132 
 133     private static void emitEvents() {
 134         for (int n = 0; n < EVENTS_PER_THREAD; n++) {
 135             MyEvent event = new MyEvent();
 136             event.begin();
 137             event.end();
 138             event.setFloatValue(1.12345f);
 139             event.setDoubleValue(1.234567890);
 140             event.setIntValue(123456);
 141             event.setLongValue(1234567890);
 142             event.setCharValue('c');
 143             event.setByteValue((byte) 12);
 144             event.setStringValue("1234567890");
 145             event.setThreadValue(Thread.currentThread());
 146             event.setClassValue(Class.class);
 147             event.commit();
 148             try {
 149                 Thread.sleep(1);
 150             } catch (InterruptedException e) {
 151                 // TODO Auto-generated catch block
 152                 e.printStackTrace();
 153             }
 154         }
 155     }
 156 
 157     static void prettyPrint() {
 158         for (EventType type : FlightRecorder.getFlightRecorder().getEventTypes()) {
 159             for (AnnotationElement a : type.getAnnotationElements()) {
 160                 printAnnotation("", a);
 161             }
 162             System.out.print("class " + removePackage(type.getName()));
 163             System.out.print(" extends Event");
 164 
 165             System.out.println(" {");
 166             List<ValueDescriptor> values = type.getFields();
 167             for (int i = 0; i < values.size(); i++) {
 168                 ValueDescriptor v = values.get(i);
 169                 for (AnnotationElement a : v.getAnnotationElements()) {
 170                     printAnnotation("  ", a);
 171                 }
 172                 System.out.println("  " + removePackage(v.getTypeName() + brackets(v.isArray())) + " " + v.getName());
 173                 if (i != values.size() - 1) {
 174                     System.out.println();
 175                 }
 176             }
 177             System.out.println("}");
 178             System.out.println();
 179         }
 180     }
 181 
 182     private static String brackets(boolean isArray) {
 183         return isArray ? "[]" : "";
 184     }
 185 
 186     private static String removePackage(String s) {
 187 
 188         int index = s.lastIndexOf(".");
 189         return s.substring(index + 1);
 190     }
 191 
 192     private static void printAnnotation(String indent, AnnotationElement a) {
 193         String name = removePackage(a.getTypeName());
 194         if (a.getValues().isEmpty()) {
 195             System.out.println(indent + "@" + name);
 196             return;
 197         }
 198         System.out.print(indent + "@" + name + "(");
 199         for (Object o : a.getValues()) {
 200             printAnnotationValue(o);
 201         }
 202         System.out.println(")");
 203     }
 204 
 205     private static void printAnnotationValue(Object o) {
 206         if (o instanceof String) {
 207             System.out.print("\"" + o + "\"");
 208         } else {
 209             System.out.print(String.valueOf(o));
 210         }
 211     }
 212 
 213 }