提交 307d461b 编写于 作者: D Denghui Dong

Revert "[JFR] Add JFR to dragonwell - jdk"

This reverts commit bb1f71c8.
上级 a00f63aa
# #
# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -595,34 +595,4 @@ COPY_FILES += $(JDK_OUTPUTDIR)/lib/sound.properties ...@@ -595,34 +595,4 @@ COPY_FILES += $(JDK_OUTPUTDIR)/lib/sound.properties
########################################################################################## ##########################################################################################
# copy hotspot trace files
HOTSPOT_TRACE_SRC_DIR := $(TOPDIR)/hotspot/src/share/vm/trace
HOTSPOT_TRACE_DST_DIR := $(JDK_OUTPUTDIR)/classes/jdk/jfr/internal/types
COPY_FILES += $(HOTSPOT_TRACE_DST_DIR)/trace.dtd \
$(HOTSPOT_TRACE_DST_DIR)/tracerelationdecls.xml \
$(HOTSPOT_TRACE_DST_DIR)/trace.xml \
$(HOTSPOT_TRACE_DST_DIR)/traceevents.xml \
$(HOTSPOT_TRACE_DST_DIR)/tracetypes.xml
$(HOTSPOT_TRACE_DST_DIR)/%.xml: $(HOTSPOT_TRACE_SRC_DIR)/%.xml
$(call install-file)
$(HOTSPOT_TRACE_DST_DIR)/trace.dtd: $(HOTSPOT_TRACE_SRC_DIR)/trace.dtd
$(call install-file)
# copy jfr configuration files
JFR_CONFIGURATION_DIR_SRC := $(JDK_TOPDIR)/src/share/lib/jfr
JFR_CONFIGURATION_DIR_DST := $(JDK_OUTPUTDIR)/lib/jfr
COPY_FILES += $(JFR_CONFIGURATION_DIR_DST)/default.jfc \
$(JFR_CONFIGURATION_DIR_DST)/profile.jfc
$(JFR_CONFIGURATION_DIR_DST)/%.jfc: $(JFR_CONFIGURATION_DIR_SRC)/%.jfc
$(call install-file)
##########################################################################################
-include $(CUSTOM_MAKE_DIR)/CopyFiles.gmk -include $(CUSTOM_MAKE_DIR)/CopyFiles.gmk
# #
# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -401,16 +401,21 @@ $(eval $(call SetupArchive,BUILD_CHARSETS_JAR, , \ ...@@ -401,16 +401,21 @@ $(eval $(call SetupArchive,BUILD_CHARSETS_JAR, , \
########################################################################################## ##########################################################################################
$(eval $(call SetupArchive,BUILD_JFR_JAR, , \ ifndef OPENJDK
SRCS := $(JDK_OUTPUTDIR)/classes, \ ifeq ($(ENABLE_JFR), true)
SUFFIXES := .class .jfc .xsd .xml .dtd, \ $(eval $(call SetupArchive,BUILD_JFR_JAR, , \
INCLUDES := jdk/jfr, \ SRCS := $(JDK_OUTPUTDIR)/classes, \
JAR := $(IMAGES_OUTPUTDIR)/lib/jfr.jar, \ SUFFIXES := .class .jfc .xsd, \
SKIP_METAINF := true, \ INCLUDES := com/oracle/jrockit/jfr \
MANIFEST := $(MAINMANIFEST), \ oracle/jrockit/jfr \
CHECK_COMPRESS_JAR := true)) jdk/jfr, \
JAR := $(IMAGES_OUTPUTDIR)/lib/jfr.jar, \
SKIP_METAINF := true, \
MANIFEST := $(MAINMANIFEST), \
CHECK_COMPRESS_JAR := true))
JARS += $(IMAGES_OUTPUTDIR)/lib/jfr.jar endif
endif
########################################################################################## ##########################################################################################
......
/* /*
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -39,13 +39,10 @@ import com.alibaba.management.TenantContainerMXBean; ...@@ -39,13 +39,10 @@ import com.alibaba.management.TenantContainerMXBean;
import com.alibaba.management.ElasticHeapMXBean; import com.alibaba.management.ElasticHeapMXBean;
import com.sun.management.HotSpotDiagnosticMXBean; import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.UnixOperatingSystemMXBean; import com.sun.management.UnixOperatingSystemMXBean;
import com.sun.management.VMOption;
import sun.management.ManagementFactoryHelper; import sun.management.ManagementFactoryHelper;
import sun.management.Util; import sun.management.Util;
import jdk.management.jfr.FlightRecorderMXBean;
/** /**
* This enum class defines the list of platform components * This enum class defines the list of platform components
* that provides monitoring and management support. * that provides monitoring and management support.
...@@ -295,27 +292,6 @@ enum PlatformComponent { ...@@ -295,27 +292,6 @@ enum PlatformComponent {
} }
}), }),
/**
* Flight Recorder.
*/
FLIGHT_RECORDER(
"jdk.management.jfr.FlightRecorderMXBean",
"jdk.management.jfr", "FlightRecorder", defaultKeyProperties(),
true,
new MXBeanFetcher<FlightRecorderMXBean>() {
public List<FlightRecorderMXBean> getMXBeans() {
HotSpotDiagnosticMXBean hsDiagMBean = ManagementFactoryHelper.getDiagnosticMXBean();
VMOption opt = hsDiagMBean.getVMOption("EnableJFR");
if (Boolean.valueOf(opt.getValue())) {
FlightRecorderMXBean m = ManagementFactoryHelper.getFlightRecorderMXBean();
if (m != null) {
return Collections.singletonList(m);
}
}
return Collections.emptyList();
}
}),
/** /**
* Elastic Heap. * Elastic Heap.
*/ */
...@@ -329,6 +305,7 @@ enum PlatformComponent { ...@@ -329,6 +305,7 @@ enum PlatformComponent {
} }
}); });
/** /**
* A task that returns the MXBeans for a component. * A task that returns the MXBeans for a component.
*/ */
...@@ -435,10 +412,9 @@ enum PlatformComponent { ...@@ -435,10 +412,9 @@ enum PlatformComponent {
<T extends PlatformManagedObject> T getSingletonMXBean(Class<T> mxbeanInterface) <T extends PlatformManagedObject> T getSingletonMXBean(Class<T> mxbeanInterface)
{ {
if (!singleton) { if (!singleton)
throw new IllegalArgumentException(mxbeanInterfaceName + throw new IllegalArgumentException(mxbeanInterfaceName +
" can have zero or more than one instances"); " can have zero or more than one instances");
}
List<T> list = getMXBeans(mxbeanInterface); List<T> list = getMXBeans(mxbeanInterface);
assert list.size() == 1; assert list.size() == 1;
...@@ -449,10 +425,9 @@ enum PlatformComponent { ...@@ -449,10 +425,9 @@ enum PlatformComponent {
T getSingletonMXBean(MBeanServerConnection mbs, Class<T> mxbeanInterface) T getSingletonMXBean(MBeanServerConnection mbs, Class<T> mxbeanInterface)
throws java.io.IOException throws java.io.IOException
{ {
if (!singleton) { if (!singleton)
throw new IllegalArgumentException(mxbeanInterfaceName + throw new IllegalArgumentException(mxbeanInterfaceName +
" can have zero or more than one instances"); " can have zero or more than one instances");
}
// ObjectName of a singleton MXBean contains only domain and type // ObjectName of a singleton MXBean contains only domain and type
assert keyProperties.size() == 1; assert keyProperties.size() == 1;
...@@ -517,9 +492,8 @@ enum PlatformComponent { ...@@ -517,9 +492,8 @@ enum PlatformComponent {
ensureInitialized(); ensureInitialized();
String cn = mxbeanInterface.getName(); String cn = mxbeanInterface.getName();
PlatformComponent pc = enumMap.get(cn); PlatformComponent pc = enumMap.get(cn);
if (pc != null && pc.getMXBeanInterface() == mxbeanInterface) { if (pc != null && pc.getMXBeanInterface() == mxbeanInterface)
return pc; return pc;
}
return null; return null;
} }
......
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.TypeLibrary;
import jdk.jfr.internal.Utils;
/**
* Describes event metadata, such as labels, descriptions and units.
* <p>
* The following example shows how {@code AnnotationElement} can be used to dynamically define events,
*
* <pre>
* <code>
* List{@literal <}AnnotationElement{@literal >} typeAnnotations = new ArrayList{@literal <}{@literal >}();
* typeannotations.add(new AnnotationElement(Name.class, "com.example.HelloWorld");
* typeAnnotations.add(new AnnotationElement(Label.class, "Hello World"));
* typeAnnotations.add(new AnnotationElement(Description.class, "Helps programmer getting started"));
*
* List{@literal <}AnnotationElement{@literal >} fieldAnnotations = new ArrayList{@literal <}{@literal >}();
* fieldAnnotations.add(new AnnotationElement(Label.class, "Message"));
*
* List{@literal <}ValueDescriptor{@literal >} fields = new ArrayList{@literal <}{@literal >}();
* fields.add(new ValueDescriptor(String.class, "message", fieldAnnotations));
*
* EventFactory f = EventFactory.create(typeAnnotations, fields);
* Event event = f.newEvent();
* event.commit();
* </code>
* </pre>
*
* @since 9
*/
public final class AnnotationElement {
private final Type type;
private final List<Object> annotationValues;
private final List<String> annotationNames;
private final boolean inBootClassLoader;
// package private
AnnotationElement(Type type, List<Object> objects, boolean boot) {
Objects.requireNonNull(type);
Objects.requireNonNull(objects);
this.type = type;
if (objects.size() != type.getFields().size()) {
StringJoiner descriptors = new StringJoiner(",", "[", "]");
for (ValueDescriptor v : type.getFields()) {
descriptors.add(v.getName());
}
StringJoiner values = new StringJoiner(",", "[", "]");
for (Object object : objects) {
descriptors.add(String.valueOf(object));
}
throw new IllegalArgumentException("Annotation " + descriptors + " for " + type.getName() + " doesn't match number of values " + values);
}
List<String> n = new ArrayList<>();
List<Object> v = new ArrayList<>();
int index = 0;
for (ValueDescriptor valueDescriptor : type.getFields()) {
Object object = objects.get(index);
if (object == null) {
throw new IllegalArgumentException("Annotation value can't be null");
}
Class<?> valueType = object.getClass();
if (valueDescriptor.isArray()) {
valueType = valueType.getComponentType();
}
checkType(Utils.unboxType(valueType));
n.add(valueDescriptor.getName());
v.add(object);
index++;
}
this.annotationValues = Utils.smallUnmodifiable(v);
this.annotationNames = Utils.smallUnmodifiable(n);
this.inBootClassLoader = boot;
}
/**
* Creates an annotation element to use for dynamically defined events.
* <p>
* Supported value types are {@code byte}, {@code int}, {@code short},
* {@code long}, {@code double}, {@code float}, {@code boolean}, {@code char},
* and {@code String}. Enums, arrays and classes, are not supported.
* <p>
* If {@code annotationType} contains annotations (directly present, indirectly
* present, or associated), then those annotation are recursively included.
* However, both the {@code annotationType} and any annotation found recursively
* must have the {@link MetadataDefinition} annotation.
* <p>
* To statically define events, see {@link Event} class.
*
* @param annotationType interface extending
* {@code java.lang.annotation.Annotation}, not {@code null}
* @param values a map with keys that match method names of the specified
* annotation interface
* @throws IllegalArgumentException if value/key is {@code null}, an unsupported
* value type is used, or a value/key is used that doesn't match the
* signatures in the {@code annotationType}
*/
public AnnotationElement(Class<? extends Annotation> annotationType, Map<String, Object> values) {
Objects.requireNonNull(annotationType);
Objects.requireNonNull(values);
Utils.checkRegisterPermission();
// copy values to avoid modification after validation
HashMap<String, Object> map = new HashMap<>(values);
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey() == null) {
throw new NullPointerException("Name of annotation method can't be null");
}
if (entry.getValue() == null) {
throw new NullPointerException("Return value for annotation method can't be null");
}
}
if (AnnotationElement.class.isAssignableFrom(annotationType) && annotationType.isInterface()) {
throw new IllegalArgumentException("Must be interface extending " + Annotation.class.getName());
}
if (!isKnownJFRAnnotation(annotationType) && annotationType.getAnnotation(MetadataDefinition.class) == null) {
throw new IllegalArgumentException("Annotation class must be annotated with jdk.jfr.MetadataDefinition to be valid");
}
if (isKnownJFRAnnotation(annotationType)) {
this.type = new Type(annotationType.getCanonicalName(), Type.SUPER_TYPE_ANNOTATION, Type.getTypeId(annotationType));
} else {
this.type = TypeLibrary.createAnnotationType(annotationType);
}
Method[] methods = annotationType.getDeclaredMethods();
if (methods.length != map.size()) {
throw new IllegalArgumentException("Number of declared methods must match size of value map");
}
List<String> n = new ArrayList<>();
List<Object> v = new ArrayList<>();
Set<String> nameSet = new HashSet<>();
for (Method method : methods) {
String fieldName = method.getName();
Object object = map.get(fieldName);
if (object == null) {
throw new IllegalArgumentException("No method in annotation interface " + annotationType.getName() + " matching name " + fieldName);
}
Class<?> fieldType = object.getClass();
if (fieldType == Class.class) {
throw new IllegalArgumentException("Annotation value for " + fieldName + " can't be class");
}
if (object instanceof Enum) {
throw new IllegalArgumentException("Annotation value for " + fieldName + " can't be enum");
}
if (!fieldType.equals(object.getClass())) {
throw new IllegalArgumentException("Return type of annotation " + fieldType.getName() + " must match type of object" + object.getClass());
}
if (fieldType.isArray()) {
Class<?> componentType = fieldType.getComponentType();
checkType(componentType);
if (componentType.equals(String.class)) {
String[] stringArray = (String[]) object;
for (int i = 0; i < stringArray.length; i++) {
if (stringArray[i] == null) {
throw new IllegalArgumentException("Annotation value for " + fieldName + " contains null");
}
}
}
} else {
fieldType = Utils.unboxType(object.getClass());
checkType(fieldType);
}
if (nameSet.contains(fieldName)) {
throw new IllegalArgumentException("Value with name '" + fieldName + "' already exists");
}
if (isKnownJFRAnnotation(annotationType)) {
ValueDescriptor vd = new ValueDescriptor(fieldType, fieldName, Collections.emptyList(), true);
type.add(vd);
}
n.add(fieldName);
v.add(object);
}
this.annotationValues = Utils.smallUnmodifiable(v);
this.annotationNames = Utils.smallUnmodifiable(n);
this.inBootClassLoader = annotationType.getClassLoader() == null;
}
/**
* Creates an annotation element to use for dynamically defined events.
* <p>
* Supported value types are {@code byte}, {@code int}, {@code short},
* {@code long}, {@code double}, {@code float}, {@code boolean}, {@code char},
* and {@code String}. Enums, arrays, and classes are not supported.
* <p>
* If {@code annotationType} contains annotations (directly present, indirectly
* present, or associated), then those annotations are recursively included.
* However, both {@code annotationType} and any annotation found recursively
* must have the {@link MetadataDefinition} annotation.
* <p>
* To statically define events, see {@link Event} class.
*
* @param annotationType interface extending
* {@code java.lang.annotation.Annotation,} not {@code null}
* @param value the value that matches the {@code value} method of the specified
* {@code annotationType}
* @throws IllegalArgumentException if value/key is {@code null}, an unsupported
* value type is used, or a value/key is used that doesn't match the
* signatures in the {@code annotationType}
*/
public AnnotationElement(Class<? extends Annotation> annotationType, Object value) {
this(annotationType, Collections.singletonMap("value", Objects.requireNonNull(value)));
}
/**
* Creates an annotation element to use for dynamically defined events.
* <p>
* Supported value types are {@code byte}, {@code short}, {@code int},
* {@code long}, {@code double}, {@code float}, {@code boolean}, {@code char},
* and {@code String}. Enums, arrays, and classes are not supported.
* <p>
* If {@code annotationType} contains annotations (directly present, indirectly
* present or associated), then those annotation are recursively included.
* However, both {@code annotationType} and any annotation found recursively
* must have the {@link MetadataDefinition} annotation.
* <p>
* To statically define events, see {@link Event} class.
*
* @param annotationType interface extending java.lang.annotation.Annotation,
* not {@code null}
*/
public AnnotationElement(Class<? extends Annotation> annotationType) {
this(annotationType, Collections.emptyMap());
}
/**
* Returns an immutable list of annotation values in an order that matches the
* value descriptors for this {@code AnnotationElement}.
*
* @return list of values, not {@code null}
*/
public List<Object> getValues() {
return annotationValues;
}
/**
* Returns an immutable list of descriptors that describes the annotation values
* for this {@code AnnotationElement}.
*
* @return the list of value descriptors for this {@code Annotation}, not
* {@code null}
*/
public List<ValueDescriptor> getValueDescriptors() {
return Collections.unmodifiableList(type.getFields());
}
/**
* Returns an immutable list of annotation elements for this
* {@code AnnotationElement}.
*
* @return a list of meta annotation, not {@code null}
*/
public List<AnnotationElement> getAnnotationElements() {
return type.getAnnotationElements();
}
/**
* Returns the fully qualified name of the annotation type that corresponds to
* this {@code AnnotationElement}.
*
* @return type name, not {@code null}
*/
public String getTypeName() {
return type.getName();
}
/**
* Returns a value for this {@code AnnotationElement}.
*
* @param name the name of the method in the annotation interface, not
* {@code null}.
*
* @return the annotation value, not {@code null}.
*
* @throws IllegalArgumentException if a method with the specified name does
* not exist the annotation
*/
public Object getValue(String name) {
Objects.requireNonNull(name);
int index = 0;
for (String n : annotationNames) {
if (name.equals(n)) {
return annotationValues.get(index);
}
index++;
}
StringJoiner valueNames = new StringJoiner(",", "[", "]");
for (ValueDescriptor v : type.getFields()) {
valueNames.add(v.getName());
}
throw new IllegalArgumentException("No value with name '" + name + "'. Valid names are " + valueNames);
}
/**
* Returns {@code true} if an annotation value with the specified name exists in
* this {@code AnnotationElement}.
*
* @param name name of the method in the annotation interface to find, not
* {@code null}
*
* @return {@code true} if method exists, {@code false} otherwise
*/
public boolean hasValue(String name) {
Objects.requireNonNull(name);
for (String n : annotationNames) {
if (name.equals(n)) {
return true;
}
}
return false;
}
/**
* Returns the first annotation for the specified type if an
* {@code AnnotationElement} with the same name exists, else {@code null}.
*
* @param <A> the type of the annotation to query for and return if it exists
* @param annotationType the Class object corresponding to the annotation type,
* not {@code null}
* @return this element's annotation for the specified annotation type if
* it it exists, else {@code null}
*/
public final <A> A getAnnotation(Class<? extends Annotation> annotationType) {
Objects.requireNonNull(annotationType);
return type.getAnnotation(annotationType);
}
/**
* Returns the type id for this {@code AnnotationElement}.
* <p>
* The type id is a unique identifier for the type in the JVM. The id might not
* be the same between JVM instances.
*
* @return the type id, not negative
*/
public long getTypeId() {
return type.getId();
}
// package private
Type getType() {
return type;
}
private static void checkType(Class<?> type) {
if (type.isPrimitive()) {
return;
}
if (type == String.class) {
return;
}
throw new IllegalArgumentException("Only primitives types or java.lang.String are allowed");
}
// Whitelist annotation classes that are allowed, even though
// they don't have @MetadataDefinition.
private static boolean isKnownJFRAnnotation(Class<? extends Annotation> annotationType) {
if (annotationType == Registered.class) {
return true;
}
if (annotationType == Threshold.class) {
return true;
}
if (annotationType == StackTrace.class) {
return true;
}
if (annotationType == Period.class) {
return true;
}
if (annotationType == Enabled.class) {
return true;
}
return false;
}
// package private
boolean isInBoot() {
return inBootClassLoader;
}
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation, signifies that the value is a boolean flag, a {@code true} or
* {@code false} value
*
* @since 9
*/
@MetadataDefinition
@ContentType
@Label("Flag")
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface BooleanFlag {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event annotation, to associate the event type with a category, in the format
* of a human-readable path.
* <p>
* The category determines how an event is presented to the user. Events that
* are in the same category are typically displayed together in graphs and
* trees. To avoid that the overlap of durational events in graphical
* representations, overlapping events must be in separate categories.
* <p>
* For example, to monitor image uploads to a web server with a separate thread
* for each upload, an event called File Upload starts when the user uploads a
* file and ends when the upload is complete. For advanced diagnostics about
* image uploads, more detailed events are created (for example, Image Read,
* Image Resize, and Image Write). During these detailed events. other low
* level-events could occur (for example, Socket Read and File Write).
* <p>
* The following example shows a visualization that avoid overlaps:
*
* <pre>
* -------------------------------------------------------------------
* | File Upload |
* ------------------------------------------------------------------
* | Image Read | Image Resize | Image Write |
* ------------------------------------------------------------------
* | Socket Read | Socket Read | | File Write |
* -------------------------------------------------------------------
* </pre>
*
* The example can be achieved by using the following categories:
*
* <table class="striped">
* <caption>Recording options and their purpose.</caption> <thead>
* <tr>
* <th scope="col">Event Name</th>
* <th scope="col">Annotation</th>
* </tr>
* </thead> <tbody>
* <tr>
* <th scope="row">File Upload</th>
* <td><code>@Category("Upload")</code></td>
* </tr>
* <tr>
* <th scope="row">Image Read</th>
* <td><code>@Category({"Upload", "Image Upload"})</code></td>
* </tr>
* <tr>
* <th scope="row">Image Resize</th>
* <td><code>@Category({"Upload", "Image Upload"})</code></td>
* </tr>
* <tr>
* <th scope="row">Image Write</th>
* <td><code>@Category({"Upload", "Image Upload"})</code></td>
* </tr>
* <tr>
* <th scope="row">Socket Read</th>
* <td><code>@Category("Java Application")</code></td>
* </tr>
* <tr>
* <th scope="row">File Write</th>
* <td><code>@Category("Java Application")</code></td>
* </tr>
* </tbody>
* </table>
* <p>
* The File Upload, Image Read, and Socket Read events happen concurrently (in
* the same thread), but the events are in different categories so they do not
* overlap in the visualization.
* <p>
* The following examples shows how the category is used to determine how events
* are visualized in a tree:
*
* <pre>
* |- Java Application
* | |- Socket Read
* | |- File Write
* |- Upload
* |- File Upload
* |- Image Upload
* |- Image Read
* |- Image Resize
* |- File Write
* </pre>
*
* @since 9
*/
@MetadataDefinition
@Target({ ElementType.TYPE })
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Category {
/**
* Returns the category names for this annotation, starting with the root.
*
* @return the category names
*/
String[] value();
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import jdk.jfr.internal.JVMSupport;
import jdk.jfr.internal.jfc.JFC;
/**
* A collection of settings and metadata describing the configuration.
*
* @since 9
*/
public final class Configuration {
private final Map<String, String> settings;
private final String label;
private final String description;
private final String provider;
private final String contents;
private final String name;
// package private
Configuration(String name, String label, String description, String provider, Map<String, String> settings, String contents) {
this.name = name;
this.label = label;
this.description = description;
this.provider = provider;
this.settings = settings;
this.contents = contents;
}
/**
* Returns the settings that specifies how a recording is configured.
* <p>
* Modifying the returned {@code Map} object doesn't change the
* configuration.
*
* @return settings, not {@code null}
*/
public Map<String, String> getSettings() {
return new LinkedHashMap<String, String>(settings);
}
/**
* Returns an identifying name (for example, {@code "default" or "profile")}.
*
* @return the name, or {@code null} if it doesn't exist
*/
public String getName() {
return this.name;
}
/**
* Returns a human-readable name (for example, {@code "Continuous" or "Profiling"}.
*
* @return the configuration name, or {@code null} if it doesn't exist
*/
public String getLabel() {
return this.label;
}
/**
* Returns a short sentence that describes the configuration (for example
* {@code "Low
* overhead configuration safe for continuous use in production
* environments"})
*
* @return the description, or {@code null} if it doesn't exist
*/
public String getDescription() {
return description;
}
/**
* Returns who created the configuration (for example {@code "Oracle"}).
*
* @return the provider, or {@code null} if it doesn't exist
*/
public String getProvider() {
return provider;
}
/**
* Returns a textual representation of the configuration (for example, the
* contents of a JFC file).
*
* @return contents, or {@code null} if it doesn't exist
*
* @see Configuration#getContents()
*/
public String getContents() {
return contents;
}
/**
* Reads a configuration from a file.
*
* @param path the file that contains the configuration, not {@code null}
* @return the read {@link Configuration}, not {@code null}
* @throws ParseException if the file can't be parsed
* @throws IOException if the file can't be read
* @throws SecurityException if a security manager exists and its
* {@code checkRead} method denies read access to the file.
*
* @see java.io.File#getPath()
* @see java.lang.SecurityManager#checkRead(java.lang.String)
*/
public static Configuration create(Path path) throws IOException, ParseException {
Objects.requireNonNull(path);
JVMSupport.ensureWithIOException();
try (Reader reader = Files.newBufferedReader(path)) {
return JFC.create(JFC.nameFromPath(path), reader);
}
}
/**
* Reads a configuration from a reader.
*
* @param reader a reader that contains the configuration contents, not
* {@code null}
* @return a configuration, not {@code null}
* @throws IOException if an I/O error occurs while trying to read contents
* from the reader
* @throws ParseException if the file can't be parsed
*/
public static Configuration create(Reader reader) throws IOException, ParseException {
Objects.requireNonNull(reader);
JVMSupport.ensureWithIOException();
return JFC.create(null, reader);
}
/**
* Returns a predefined configuration.
* <p>
* See {@link Configuration#getConfigurations()} for available configuration
* names.
*
* @param name the name of the configuration (for example, "default" or
* "profile")
* @return a configuration, not {@code null}
*
* @throws IOException if a configuration with the given name does not
* exist, or if an I/O error occurs while reading the
* configuration file
* @throws ParseException if the configuration file can't be parsed
*/
public static Configuration getConfiguration(String name) throws IOException, ParseException {
JVMSupport.ensureWithIOException();
return JFC.getPredefined(name);
}
/**
* Returns an immutable list of predefined configurations for this JVM.
*
* @return the list of predefined configurations, not {@code null}
*/
public static List<Configuration> getConfigurations() {
if (JVMSupport.isNotAvailable()) {
return new ArrayList<>();
}
return Collections.unmodifiableList(JFC.getConfigurations());
}
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Meta annotation, signifies that an annotation represents a content type, such
* as a time span or a frequency.
*
* @since 9
*/
@MetadataDefinition
@Label("Content Type")
@Description("Semantic meaning of a value")
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentType {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation, signifies that a value represents an amount of data (for example, bytes).
*
* @since 9
*/
@MetadataDefinition
@ContentType
@Label("Data Amount")
@Description("Amount of data")
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface DataAmount {
/**
* Unit for bits
*/
public static final String BITS = "BITS";
/**
* Unit for bytes
*/
public static final String BYTES = "BYTES";
/**
* Returns the unit for the data amount, by default bytes.
*
* @return the data amount unit, default {@code #BYTES}, not {@code null}
*/
String value() default BYTES;
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that describes an element by using a sentence or two.
* <p>
* Use sentence-style capitalization, capitalize the first letter of the first
* word, and any proper names such as the word Java. If the description is one
* sentence, a period should not be included.
*
* @since 9
*/
@MetadataDefinition
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Description {
/**
* Returns a sentence or two that describes the annotated element.
*
* @return a description, not {@code null}
*/
String value();
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event annotation, determines if an event should be enabled by default.
* <p>
* If an event doesn't have the annotation, then by default event is enabled.
*
* @since 9
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@MetadataDefinition
public @interface Enabled {
/**
* Setting name {@code "enabled"}, signifies that the event should be
* recorded.
*/
public final static String NAME = "enabled";
/**
* Returns {@code true} if by default the event should be enabled, {@code false} otherwise.
*
* @return {@code true} if by default the event should be enabled by default, {@code false} otherwise
*/
boolean value() default true;
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
/**
* Base class for events, to be subclassed in order to define events and their
* fields.
* <p>
* The following example shows how to implement an {@code Event} class.
*
* <pre>
* <code>
* import jdk.jfr.Event;
* import jdk.jfr.Description;
* import jdk.jfr.Label;
*
* public class Example {
*
* &#064;Label("Hello World")
* &#064;Description("Helps programmer getting started")
* static class HelloWorld extends Event {
* &#064;Label("Message")
* String message;
* }
*
* public static void main(String... args) {
* HelloWorld hwe = new HelloWorld();
* hwe.message = "hello, world!";
* hwe.commit();
* }
* }
* </code>
* </pre>
* <p>
* After an event is allocated and its field members are populated, it can be
* written to the Flight Recorder system by using the {@code #commit()} method.
* <p>
* By default, an event is enabled. To disable an event annotate the
* {@link Event} class with {@code @Enabled(false)}.
* <p>
* Supported field types are the Java primitives: {@code boolean}, {@code char},
* {@code byte}, {@code short}, {@code int}, {@code long}, {@code float}, and
* {@code double}. Supported reference types are: {@code String}, {@code Thread}
* and {@code Class}. Arrays, enums, and other reference types are silently
* ignored and not included. Fields that are of the supported types can be
* excluded by using the transient modifier. Static fields, even of the
* supported types, are not included.
* <p>
* Tools can visualize data in a meaningful way when annotations are used (for
* example, {@code Label}, {@code Description}, and {@code Timespan}).
* Annotations applied to an {@link Event} class or its fields are included if
* they are present (indirectly, directly, or associated), have the
* {@code MetadataDefinition} annotation, and they do not contain enums, arrays,
* or classes.
* <p>
* Gathering data to store in an event can be expensive. The
* {@link Event#shouldCommit} method can be used to verify whether an event
* instance would actually be written to the system when the {@code #commit()}
* method is invoked. If {@link Event#shouldCommit} returns false, then those
* operations can be avoided.
*
* @since 9
*/
@Enabled(true)
@StackTrace(true)
@Registered(true)
abstract public class Event {
/**
* Sole constructor, for invocation by subclass constructors, typically
* implicit.
*/
protected Event() {
}
/**
* Starts the timing of this event.
*/
final public void begin() {
}
/**
* Ends the timing of this event.
*
* The {@code end} method must be invoked after the {@code begin} method.
*/
final public void end() {
}
/**
* Writes the field values, time stamp, and event duration to the Flight
* Recorder system.
* <p>
* If the event starts with an invocation of the {@code begin} method, but does
* not end with an explicit invocation of the {@code end} method, then the event
* ends when the {@code commit} method is invoked.
*/
final public void commit() {
}
/**
* Returns {@code true} if at least one recording is running, and the
* enabled setting for this event is set to {@code true}, otherwise
* {@code false} is returned.
*
* @return {@code true} if event is enabled, {@code false} otherwise
*/
final public boolean isEnabled() {
return false;
}
/**
* Returns {@code true} if the enabled setting for this event is set to
* {@code true} and if the duration is within the threshold for the event,
* {@code false} otherwise. The threshold is the minimum threshold for all
* running recordings.
*
* @return {@code true} if the event can be written to the Flight Recorder
* system, {@code false} otherwise
*/
final public boolean shouldCommit() {
return false;
}
/**
* Sets a field value.
* <p>
* Applicable only if the event is dynamically defined using the
* {@code EventFactory} class.
* <p>
* The supplied {@code index} corresponds to the index of the
* {@link ValueDescriptor} object passed to the factory method of the
* {@code EventFactory} class.
*
* @param index the index of the field that is passed to
* {@code EventFactory#create(String, java.util.List, java.util.List)}
* @param value value to set, can be {@code null}
* @throws UnsupportedOperationException if it's not a dynamically generated
* event
* @throws IndexOutOfBoundsException if {@code index} is less than {@code 0} or
* greater than or equal to the number of fields specified for the event
*
* @see EventType#getFields()
* @see EventFactory
*/
final public void set(int index, Object value) {
}
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import jdk.jfr.internal.EventClassBuilder;
import jdk.jfr.internal.JVMSupport;
import jdk.jfr.internal.MetadataRepository;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.Utils;
/**
* Class for defining an event at runtime.
* <p>
* It's highly recommended that the event is defined at compile time, if the
* field layout is known, so the Java Virtual Machine (JVM) can optimize the
* code, possibly remove all instrumentation if Flight Recorder is inactive or
* if the enabled setting for this event is set to {@code false}.
* <p>
* To define an event at compile time, see {@link Event}.
* <p>
* The following example shows how to implement a dynamic {@code Event} class.
*
* <pre>
* {
* &#64;code
* List<ValueDescriptor> fields = new ArrayList<>();
* List<AnnotationElement> messageAnnotations = Collections.singletonList(new AnnotationElement(Label.class, "Message"));
* fields.add(new ValueDescriptor(String.class, "message", messageAnnotations));
* List<AnnotationElement> numberAnnotations = Collections.singletonList(new AnnotationElement(Label.class, "Number"));
* fields.add(new ValueDescriptor(int.class, "number", numberAnnotations));
*
* String[] category = { "Example", "Getting Started" };
* List<AnnotationElement> eventAnnotations = new ArrayList<>();
* eventAnnotations.add(new AnnotationElement(Name.class, "com.example.HelloWorld"));
* eventAnnotations.add(new AnnotationElement(Label.class, "Hello World"));
* eventAnnotations.add(new AnnotationElement(Description.class, "Helps programmer getting started"));
* eventAnnotations.add(new AnnotationElement(Category.class, category));
*
* EventFactory f = EventFactory.create(eventAnnotations, fields);
*
* Event event = f.newEvent();
* event.set(0, "hello, world!");
* event.set(1, 4711);
* event.commit();
* }
* </pre>
*
* @since 9
*/
public final class EventFactory {
private static final long REGSITERED_ID = Type.getTypeId(Registered.class);
private final Class<? extends Event> eventClass;
private final MethodHandle constructorHandle;
private final List<AnnotationElement> sanitizedAnnotation;
private final List<ValueDescriptor> sanitizedFields;
private EventFactory(Class<? extends Event> eventClass, List<AnnotationElement> sanitizedAnnotation, List<ValueDescriptor> sanitizedFields) throws IllegalAccessException, NoSuchMethodException, SecurityException {
this.constructorHandle = MethodHandles.lookup().unreflectConstructor(eventClass.getConstructor());
this.eventClass = eventClass;
this.sanitizedAnnotation = sanitizedAnnotation;
this.sanitizedFields = sanitizedFields;
}
/**
* Creates an {@code EventFactory} object.
* <p>
* The order of the value descriptors specifies the index to use when setting
* event values.
*
* @param annotationElements list of annotation elements that describes the
* annotations on the event, not {@code null}
*
* @param fields list of descriptors that describes the fields of the event, not
* {@code null}
*
* @return event factory, not {@code null}
*
* @throws IllegalArgumentException if the input is not valid. For example,
* input might not be valid if the field type or name is not valid in
* the Java language or an annotation element references a type that
* can't be found.
*
* @throws SecurityException if a security manager exists and the caller does
* not have {@code FlightRecorderPermission("registerEvent")}
*
* @see Event#set(int, Object)
*/
public static EventFactory create(List<AnnotationElement> annotationElements, List<ValueDescriptor> fields) {
Objects.requireNonNull(fields);
Objects.requireNonNull(annotationElements);
JVMSupport.ensureWithInternalError();
Utils.checkRegisterPermission();
List<AnnotationElement> sanitizedAnnotation = Utils.sanitizeNullFreeList(annotationElements, AnnotationElement.class);
List<ValueDescriptor> sanitizedFields = Utils.sanitizeNullFreeList(fields, ValueDescriptor.class);
Set<String> nameSet = new HashSet<>();
for (ValueDescriptor v : sanitizedFields) {
String name = v.getName();
if (v.isArray()) {
throw new IllegalArgumentException("Array types are not allowed for fields");
}
if (!Type.isValidJavaFieldType(v.getTypeName())) {
throw new IllegalArgumentException(v.getTypeName() + " is not a valid type for an event field");
}
if (!Type.isValidJavaIdentifier(v.getName())) {
throw new IllegalArgumentException(name + " is not a valid name for an event field");
}
if (nameSet.contains(name)) {
throw new IllegalArgumentException("Name of fields must be unique. Found two instances of " + name);
}
nameSet.add(name);
}
// Prevent event from being registered in <clinit>
// and only use annotations that can be resolved (those in boot class loader)
boolean needRegister = true;
List<AnnotationElement> bootAnnotations = new ArrayList<>();
for (AnnotationElement ae : sanitizedAnnotation) {
long id = ae.getTypeId();
if (ae.isInBoot()) {
if (id == REGSITERED_ID) {
if (Boolean.FALSE.equals(ae.getValue("value"))) {
needRegister = false;
}
} else {
bootAnnotations.add(ae);
}
}
}
bootAnnotations.add(new AnnotationElement(Registered.class, false));
EventClassBuilder ecb = new EventClassBuilder(bootAnnotations, sanitizedFields);
Class<? extends Event> eventClass = ecb.build();
if (needRegister) {
MetadataRepository.getInstance().register(eventClass, sanitizedAnnotation, sanitizedFields);
}
try {
return new EventFactory(eventClass, sanitizedAnnotation, sanitizedFields);
} catch (IllegalAccessException e) {
throw new IllegalAccessError("Could not accees constructor of generated event handler, " + e.getMessage());
} catch (NoSuchMethodException e) {
throw new InternalError("Could not find constructor in generated event handler, " + e.getMessage());
}
}
/**
* Instantiates an event, so it can be populated with data and written to the
* Flight Recorder system.
* <p>
* Use the {@link Event#set(int, Object)} method to set a value.
*
* @return an event instance, not {@code null}
*/
public Event newEvent() {
try {
return (Event) constructorHandle.invoke();
} catch (Throwable e) {
throw new InstantiationError("Could not instantaite dynamically generated event class " + eventClass.getName() + ". " + e.getMessage());
}
}
/**
* Returns the event type that is associated with this event factory.
*
* @return event type that is associated with this event factory, not
* {@code null}
*
* @throws java.lang.IllegalStateException if the event factory is created with
* the {@code Registered(false)} annotation and the event class is not
* manually registered before the invocation of this method
*/
public EventType getEventType() {
return EventType.getEventType(eventClass);
}
/**
* Registers an unregistered event.
* <p>
* By default, the event class associated with this event factory is registered
* when the event factory is created, unless the event has the
* {@link Registered} annotation.
* <p>
* A registered event class can write data to Flight Recorder and event metadata
* can be obtained by invoking {@link FlightRecorder#getEventTypes()}.
* <p>
* If the event class associated with this event factory is already registered,
* the call to this method is ignored.
*
* @throws SecurityException if a security manager exists and the caller
* does not have {@code FlightRecorderPermission("registerEvent")}
* @see Registered
* @see FlightRecorder#register(Class)
*/
public void register() {
MetadataRepository.getInstance().register(eventClass, sanitizedAnnotation, sanitizedFields);
}
/**
* Unregisters the event that is associated with this event factory.
* <p>
* A unregistered event class can't write data to Flight Recorder and event
* metadata can't be obtained by invoking
* {@link FlightRecorder#getEventTypes()}.
* <p>
* If the event class associated with this event factory is not already
* registered, the call to this method is ignored.
*
* @throws SecurityException if a security manager exists and the caller does
* not have {@code FlightRecorderPermission("registerEvent")}
* @see Registered
* @see FlightRecorder#unregister(Class)
*/
public void unregister() {
MetadataRepository.getInstance().unregister(eventClass);
}
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.time.Duration;
import java.util.Map;
/**
* Convenience class for applying event settings to a recording.
* <p>
* An event setting object for a recording can be obtained by invoking
* the {@link Recording#enable(String)} method which is configured using method
* chaining.
* <p>
* The following example shows how to use the {@code EventSetting} class.
* <pre>
* {@code
* Recording r = new Recording();
* r.enable("com.oracle.jdk.CPULoad")
* .withPeriod(Duration.ofSeconds(1));
* r.enable("com.oracle.jdk.FileWrite")
* .withoutStackTrace()
* .withThreshold(Duration.ofNanos(10));
* r.start();
* Thread.sleep(10_000);
* r.stop();
* r.dump(Files.createTempFile("recording", ".jfr"));
*
* }
* </pre>
* @since 9
*/
public abstract class EventSettings {
// package private
EventSettings() {
}
/**
* Enables stack traces for the event that is associated with this event setting.
*
* Equivalent to invoking the {@code with("stackTrace", "true")} method.
*
* @return event settings object for further configuration, not {@code null}
*/
final public EventSettings withStackTrace() {
return with(StackTrace.NAME, "true");
}
/**
* Disables stack traces for the event that is associated with this event setting.
*
* Equivalent to invoking the {@code with("stackTrace", "false")} method.
*
* @return event settings object for further configuration, not {@code null}
*/
final public EventSettings withoutStackTrace() {
return with(StackTrace.NAME, "false");
}
/**
* Specifies that a threshold is not used.
* <p>
* This is a convenience method, equivalent to invoking the
* {@code with("threshold", "0 s")} method.
*
* @return event settings object for further configuration, not {@code null}
*/
final public EventSettings withoutThreshold() {
return with(Threshold.NAME, "0 s");
}
/**
* Sets the interval for the event that is associated with this event setting.
*
* @param duration the duration, not {@code null}
*
* @return event settings object for further configuration, not {@code null}
*/
final public EventSettings withPeriod(Duration duration) {
return with(Period.NAME, duration.toNanos() + " ns");
}
/**
* Sets the threshold for the event that is associated with this event setting.
*
* @param duration the duration, or {@code null} if no duration is used
*
* @return event settings object for further configuration, not {@code null}
*/
final public EventSettings withThreshold(Duration duration) {
if (duration == null) {
return with(Threshold.NAME, "0 ns");
} else {
return with(Threshold.NAME, duration.toNanos() + " ns");
}
}
/**
* Sets a setting value for the event that is associated with this event setting.
*
* @param name the name of the setting (for example, {@code "threshold"})
*
* @param value the value to set (for example {@code "20 ms"} not
* {@code null})
*
* @return event settings object for further configuration, not {@code null}
*/
abstract public EventSettings with(String name, String value);
/**
* Creates a settings {@code Map} for the event that is associated with this
* event setting.
*
* @return a settings {@code Map}, not {@code null}
*/
abstract Map<String, String> toMap();
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import jdk.jfr.internal.JVMSupport;
import jdk.jfr.internal.MetadataRepository;
import jdk.jfr.internal.PlatformEventType;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.Utils;
/**
* Describes an event, its fields, settings and annotations.
*
* @since 9
*/
public final class EventType {
private final PlatformEventType platformEventType;
private final List<String> UNCATEGORIZED = Collections.singletonList("Uncategorized");
private Map<String, ValueDescriptor> cache; // create lazy to avoid memory overhead
// helper constructor
EventType(PlatformEventType platformEventType) {
this.platformEventType = platformEventType;
}
/**
* Returns an immutable list of descriptors that describe the event fields of
* this event type.
*
* @return the list of field descriptors, not {@code null}
*/
public List<ValueDescriptor> getFields() {
return platformEventType.getFields();
}
/**
* Returns the field with the specified name, or {@code null} if it doesn't
* exist.
*
* @return a value descriptor that describes the field, or <code>null</code> if
* the field with the specified name doesn't exist
*
* @return a value descriptor, or <code>null</code> if it doesn't exist
*/
public ValueDescriptor getField(String name) {
Objects.requireNonNull(name);
if (cache == null) {
List<ValueDescriptor> fields = getFields();
Map<String, ValueDescriptor> newCache = new LinkedHashMap<String, ValueDescriptor>(fields.size());
for (ValueDescriptor v :fields) {
newCache.put(v.getName(), v);
}
cache = newCache;
}
return cache.get(name);
}
/**
* Returns an identifier for the event (for example,
* {@code "jdk.jfr.CPULoad"}).
* <p>
* The identifier is the fully qualified name of the event class, if not set using
* the {@link Name} annotation.
*
* @return the name, not {@code null}
*
* @see Name
*/
public String getName() {
return platformEventType.getName();
}
/**
* Returns a human-readable name (for example, {@code "CPU Load"}).
* <p>
* The label of an event class can be set with {@link Label}.
*
* @return the label, or {@code null} if a label is not been set
*
* @see Label
*/
public String getLabel() {
return platformEventType.getLabel();
}
/**
* Returns a unique ID for this event type in the Java Virtual Machine (JVM).
*
* @return the ID that is used in the JVM
*/
public long getId() {
return platformEventType.getId();
}
/**
* Returns an immutable list of annotation elements for this event type.
*
* @return an immutable list of annotations or an empty list if no
* annotations exists, not {@code null}
*/
public List<AnnotationElement> getAnnotationElements() {
return platformEventType.getAnnotationElements();
}
/**
* Returns {@code true} if the event is enabled and at least one recording is
* running, {@code false} otherwise.
* <p>
* By default, the event is enabled. The event can be enabled or disabled by
* setting the enabled setting to {@code true} or {@code false}, programmatically or by using a
* configuration file. The event can also be disabled by annotating event with
* the {@code @Enabled(false)} annotation.
*
* @return true if event is enabled, false otherwise
*
* @see Enabled
* @see Recording#enable(Class)
*/
public boolean isEnabled() {
return platformEventType.isEnabled();
}
/**
* Returns a short sentence that describes the event class.
* <p>
* The description of an event class can be set with {@link Description}.
*
* @return the description, or {@code null} if no description exists
*
* @see Description
*/
public String getDescription() {
return platformEventType.getDescription();
}
/**
* Returns the first annotation for the specified type if an annotation
* element with the same name is directly present, otherwise {@code null}.
*
* @param <A> the type of the annotation to query for and return if present
* @param annotationClass the {@code Class} object that corresponds to the
* annotation type, not {@code null}
* @return this element's annotation for the specified annotation type if
* directly present, else {@code null}
*/
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return platformEventType.getAnnotation(annotationClass);
}
/**
* Returns the event type for an event class, or {@code null} if it doesn't
* exist.
*
* @param eventClass the event class, not {@code null}
* @return the event class, or null if class doesn't exist
*
* @throws IllegalArgumentException if {@code eventClass} is an abstract class
*
* @throws IllegalStateException if the class is annotated with
* {@code Registered(false)}, but not manually registered
*/
public static EventType getEventType(Class<? extends Event> eventClass) {
Objects.requireNonNull(eventClass);
Utils.ensureValidEventSubclass(eventClass);
JVMSupport.ensureWithInternalError();
return MetadataRepository.getInstance().getEventType(eventClass);
}
/**
* Returns an immutable list of the setting descriptors that describe the available
* event settings for this event type.
*
* @return the list of setting descriptors for this event type, not
* {@code null}
*/
public List<SettingDescriptor> getSettingDescriptors() {
return Collections.unmodifiableList(platformEventType.getSettings());
}
/**
* Returns the list of human-readable names that makes up the categories for
* this event type (for example, "Java Application", "Statistics").
*
* @return an immutable list of category names, or a list with the name
* "Uncategorized" if no category is set
*
* @see Category
*/
public List<String> getCategoryNames() {
Category c = platformEventType.getAnnotation(Category.class);
if (c == null) {
return UNCATEGORIZED;
}
return Collections.unmodifiableList(Arrays.asList(c.value()));
}
// package private
Type getType() {
return platformEventType;
}
// package private
PlatformEventType getPlatformEventType() {
return platformEventType;
}
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that signifies that an element is experimental and may change
* without notice.
* <p>
* Clients that visualize Flight Recorder events should <em>not</em> show the
* events or fields annotated with the {@code Experimental} annotation by
* default. This annotation allows event producers the freedom to try out new
* events without committing to them.
* <p>
* Clients may provide a check box (for example, in a preference page) where a
* user can opt-in to display experimental data. If the user decide to do so,
* the user interface should mark experimental events or fields so users can
* distinguish them from non-experimental events.
* <p>
* This annotation is inherited.
*
* @since 9
*/
@MetadataDefinition
@Label("Experimental")
@Description("Element is not to be shown to a user by default")
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.TYPE })
public @interface Experimental {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import static jdk.jfr.internal.LogLevel.DEBUG;
import static jdk.jfr.internal.LogLevel.INFO;
import static jdk.jfr.internal.LogTag.JFR;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import jdk.jfr.internal.JVM;
import jdk.jfr.internal.JVMSupport;
import jdk.jfr.internal.LogLevel;
import jdk.jfr.internal.Logger;
import jdk.jfr.internal.MetadataRepository;
import jdk.jfr.internal.Options;
import jdk.jfr.internal.PlatformRecorder;
import jdk.jfr.internal.PlatformRecording;
import jdk.jfr.internal.Repository;
import jdk.jfr.internal.RequestEngine;
import jdk.jfr.internal.Utils;
/**
* Class for accessing, controlling, and managing Flight Recorder.
* <p>
* This class provides the methods necessary for creating, starting, stopping,
* and destroying recordings.
*
* @since 9
*/
public final class FlightRecorder {
private static volatile FlightRecorder platformRecorder;
private static volatile boolean initialized;
private final PlatformRecorder internal;
private FlightRecorder(PlatformRecorder internal) {
this.internal = internal;
}
/**
* Returns an immutable list of the available recordings.
* <p>
* A recording becomes available when it is created. It becomes unavailable when it
* is in the {@code CLOSED} state, typically after a call to
* {@link Recording#close()}.
*
* @return a list of recordings, not {@code null}
*/
public List<Recording> getRecordings() {
List<Recording> recs = new ArrayList<>();
for (PlatformRecording internal : internal.getRecordings()) {
recs.add(internal.getRecording());
}
return Collections.unmodifiableList(recs);
}
/**
* Creates a snapshot of all available recorded data.
* <p>
* A snapshot is a synthesized recording in a stopped state. If no data is
* available, a recording with size {@code 0} is returned.
* <p>
* A snapshot provides stable access to data for later operations (for example,
* operations to change the interval or to reduce the data size).
* <p>
* Example,
*
* <pre>
* <code>
* try (Recording snapshot = FlightRecorder.getFlightRecorder().takeSnapshot()) {
* if (snapshot.getSize() &gt; 0) {
* snapshot.setMaxSize(100_000_000);
* snapshot.setMaxAge(Duration.ofMinutes(5));
* snapshot.dump(Paths.get("snapshot.jfr"));
* }
* }
* </code>
* </pre>
*
* The caller must close the recording when access to the data is no longer
* needed.
*
* @return a snapshot of all available recording data, not {@code null}
*/
public Recording takeSnapshot() {
return internal.newSnapshot();
}
/**
* Registers an event class.
* <p>
* If the event class is already registered, then the invocation of this method is
* ignored.
*
* @param eventClass the event class to register, not {@code null}
*
* @throws IllegalArgumentException if class is abstract or not a subclass
* of {@link Event}
* @throws SecurityException if a security manager exists and the caller
* does not have {@code FlightRecorderPermission("registerEvent")}
*/
public static void register(Class<? extends Event> eventClass) {
Objects.requireNonNull(eventClass);
if (JVMSupport.isNotAvailable()) {
return;
}
Utils.ensureValidEventSubclass(eventClass);
MetadataRepository.getInstance().register(eventClass);
}
/**
* Unregisters an event class.
* <p>
* If the event class is not registered, then the invocation of this method is
* ignored.
*
* @param eventClass the event class to unregistered, not {@code null}
* @throws IllegalArgumentException if a class is abstract or not a subclass
* of {@link Event}
*
* @throws SecurityException if a security manager exists and the caller
* does not have {@code FlightRecorderPermission("registerEvent")}
*/
public static void unregister(Class<? extends Event> eventClass) {
Objects.requireNonNull(eventClass);
if (JVMSupport.isNotAvailable()) {
return;
}
Utils.ensureValidEventSubclass(eventClass);
MetadataRepository.getInstance().unregister(eventClass);
}
/**
* Returns the Flight Recorder for the platform.
*
* @return a Flight Recorder instance, not {@code null}
*
* @throws IllegalStateException if the platform Flight Recorder couldn't be
* created (for example, if the file repository can't be created or
* accessed)
*
* @throws SecurityException if a security manager exists and the caller does
* not have {@code FlightRecorderPermission("accessFlightRecorder")}
*/
public static FlightRecorder getFlightRecorder() throws IllegalStateException, SecurityException {
synchronized (PlatformRecorder.class) {
Utils.checkAccessFlightRecorder();
JVMSupport.ensureWithIllegalStateException();
if (platformRecorder == null) {
try {
platformRecorder = new FlightRecorder(new PlatformRecorder());
} catch (IllegalStateException ise) {
throw ise;
} catch (Exception e) {
throw new IllegalStateException("Can't create Flight Recorder. " + e.getMessage(), e);
}
// Must be in synchronized block to prevent instance leaking out
// before initialization is done
initialized = true;
Logger.log(JFR, INFO, "Flight Recorder initialized");
Logger.log(JFR, DEBUG, "maxchunksize: " + Options.getMaxChunkSize()+ " bytes");
Logger.log(JFR, DEBUG, "memorysize: " + Options.getMemorySize()+ " bytes");
Logger.log(JFR, DEBUG, "globalbuffersize: " + Options.getGlobalBufferSize()+ " bytes");
Logger.log(JFR, DEBUG, "globalbuffercount: " + Options.getGlobalBufferCount());
Logger.log(JFR, DEBUG, "dumppath: " + Options.getDumpPath());
Logger.log(JFR, DEBUG, "samplethreads: " + Options.getSampleThreads());
Logger.log(JFR, DEBUG, "stackdepth: " + Options.getStackDepth());
Logger.log(JFR, DEBUG, "threadbuffersize: " + Options.getThreadBufferSize());
Logger.log(JFR, LogLevel.INFO, "Created repository " + Repository.getRepository().getRepositoryPath().toString());
PlatformRecorder.notifyRecorderInitialized(platformRecorder);
}
}
return platformRecorder;
}
/**
* Adds a callback for a periodic event.
* <p>
* The implementation of the hook should return as soon as possible, to
* avoid blocking other Flight Recorder operations. The hook should emit
* one or more events of the specified type. When a hook is added, the
* interval at which the call is invoked is configurable using the
* {@code "period"} setting.
*
* @param eventClass the class that the hook should run for, not {@code null}
* @param hook the hook, not {@code null}
* @throws IllegalArgumentException if a class is not a subclass of
* {@link Event}, is abstract, or the hook is already added
* @throws IllegalStateException if the event class has the
* {@code Registered(false)} annotation and is not registered manually
* @throws SecurityException if a security manager exists and the caller
* does not have {@code FlightRecorderPermission("registerEvent")}
*/
public static void addPeriodicEvent(Class<? extends Event> eventClass, Runnable hook) throws SecurityException {
Objects.requireNonNull(eventClass);
Objects.requireNonNull(hook);
if (JVMSupport.isNotAvailable()) {
return;
}
Utils.ensureValidEventSubclass(eventClass);
Utils.checkRegisterPermission();
AccessControlContext acc = AccessController.getContext();
RequestEngine.addHook(acc, EventType.getEventType(eventClass).getPlatformEventType(), hook);
}
/**
* Removes a callback hook for a periodic event.
*
* @param hook the hook to remove, not {@code null}
* @return {@code true} if hook is removed, {@code false} otherwise
* @throws SecurityException if a security manager exists and the caller
* does not have {@code FlightRecorderPermission("registerEvent")}
*/
public static boolean removePeriodicEvent(Runnable hook) throws SecurityException {
Objects.requireNonNull(hook);
Utils.checkRegisterPermission();
if (JVMSupport.isNotAvailable()) {
return false;
}
return RequestEngine.removeHook(hook);
}
/**
* Returns an immutable list that contains all currently registered events.
*
* By default, events are registered when they are first used, typically
* when an event object is allocated. To ensure an event is visible early,
* registration can be triggered by invoking the
* {@link FlightRecorder#register(Class)} method.
*
* @return list of events, not {@code null}
*/
public List<EventType> getEventTypes() {
return Collections.unmodifiableList(MetadataRepository.getInstance().getRegisteredEventTypes());
}
/**
* Adds a recorder listener and captures the {@code AccessControlContext} to
* use when invoking the listener.
* <p>
* If Flight Recorder is already initialized when the listener is added, the the method
* {@link FlightRecorderListener#recorderInitialized(FlightRecorder)} method is
* invoked before returning from this method.
*
* @param changeListener the listener to add, not {@code null}
*
* @throws SecurityException if a security manager exists and the caller
* does not have
* {@code FlightRecorderPermission("accessFlightRecorder")}
*/
public static void addListener(FlightRecorderListener changeListener) {
Objects.requireNonNull(changeListener);
Utils.checkAccessFlightRecorder();
if (JVMSupport.isNotAvailable()) {
return;
}
PlatformRecorder.addListener(changeListener);
}
/**
* Removes a recorder listener.
* <p>
* If the same listener is added multiple times, only one instance is
* removed.
*
* @param changeListener listener to remove, not {@code null}
*
* @throws SecurityException if a security manager exists and the caller
* does not have
* {@code FlightRecorderPermission("accessFlightRecorder")}
*
* @return {@code true}, if the listener could be removed, {@code false}
* otherwise
*/
public static boolean removeListener(FlightRecorderListener changeListener) {
Objects.requireNonNull(changeListener);
Utils.checkAccessFlightRecorder();
if (JVMSupport.isNotAvailable()) {
return false;
}
return PlatformRecorder.removeListener(changeListener);
}
/**
* Returns {@code true} if the Java Virtual Machine (JVM) has Flight Recorder capabilities.
* <p>
* This method can quickly check whether Flight Recorder can be
* initialized, without actually doing the initialization work. The value may
* change during runtime and it is not safe to cache it.
*
* @return {@code true}, if Flight Recorder is available, {@code false}
* otherwise
*
* @see FlightRecorderListener for callback when Flight Recorder is
* initialized
*/
public static boolean isAvailable() {
if (JVMSupport.isNotAvailable()) {
return false;
}
return JVM.getJVM().isAvailable();
}
/**
* Returns {@code true} if Flight Recorder is initialized.
*
* @return {@code true}, if Flight Recorder is initialized,
* {@code false} otherwise
*
* @see FlightRecorderListener for callback when Flight Recorder is
* initialized
*/
public static boolean isInitialized() {
return initialized;
}
// package private
PlatformRecording newInternalRecording(Map<String, String> settings) {
return internal.newRecording(settings);
}
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
/**
* Callback interface to monitor Flight Recorder's life cycle.
*
* @since 9
*/
public interface FlightRecorderListener {
/**
* Receives notification when Flight Recorder is initialized.
* <p>
* This method is also be invoked when a listener is added to an already
* initialized Flight Recorder.
* <p>
* This method allows clients to implement their own initialization mechanism
* that is executed before a {@code FlightRecorder} instance is returned by
* {@code FlightRecorder#getFlightRecorder()}.
*
* @implNote This method should return as soon as possible, to avoid blocking
* initialization of Flight Recorder. To avoid deadlocks or unexpected
* behavior, this method should not call
* {@link FlightRecorder#getFlightRecorder()} or start new recordings.
*
* @implSpec The default implementation of this method is empty.
*
* @param recorder Flight Recorder instance, not {@code null}
*
* @see FlightRecorder#addListener(FlightRecorderListener)
*/
default void recorderInitialized(FlightRecorder recorder) {
}
/**
* Receives notification when the state of a recording changes.
* <p>
* Callback is invoked when a recording reaches the {@code RUNNING},
* {@code STOPPED} and {@code CLOSED} state.
*
* @implNote The implementation of this method should return as soon as possible
* to avoid blocking normal operation of Flight Recorder.
*
* @implSpec The default implementation of this method is empty.
*
* @param recording the recording where the state change occurred, not
* {@code null}
*
* @see FlightRecorder#addListener(FlightRecorderListener)
* @see RecordingState
*
*/
default void recordingStateChanged(Recording recording) {
}
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import jdk.jfr.internal.PlatformEventType;
import jdk.jfr.internal.PlatformRecording;
import jdk.jfr.internal.PrivateAccess;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.Utils;
/**
* Permission for controlling access to Flight Recorder.
* <p>
* The following table provides a summary description of what the permission
* allows, and discusses the risks of granting code the permission.
*
* <table class="striped">
* <caption style="display:none">Table shows permission target name,
* what the permission allows, and associated risks</caption>
* <thead>
* <tr>
* <th scope="col">Permission Target Name</th>
* <th scope="col">What the Permission Allows</th>
* <th scope="col">Risks of Allowing this Permission</th>
* </tr>
* </thead>
*
* <tbody>
* <tr>
* <th scope="row">accessFlightRecorder</th>
* <td>Ability to create a Flight Recorder instance, register callbacks to
* monitor Flight Recorder's life cycle and control an already existing instance
* of Flight Recorder, which can record and dump runtime information, such as
* stack traces, class names and data in user defined events.</td>
* <td>A malicious user may be able to extract sensitive information stored in
* events and interrupt Flight Recorder by installing listeners or hooks that
* never finishes.</td>
* </tr>
* <tr>
* <th scope="row">registerEvent</th>
* <td>Ability to register events, write data to the Flight Recorder buffers
* and execute code in a callback function for periodic events.
*
* <td>A malicious user may be able to write sensitive information to Flight
* Recorder buffers.</td>
* </tr>
* </tbody>
* </table>
*
* <p>
* Programmers do not normally create {@code FlightRecorderPermission} objects
* directly. Instead they are created by the security policy code based on
* reading the security policy file.
*
* @since 9
*
* @see java.security.BasicPermission
* @see java.security.Permission
* @see java.security.Permissions
* @see java.security.PermissionCollection
* @see java.lang.SecurityManager
*
*/
@SuppressWarnings("serial")
public final class FlightRecorderPermission extends java.security.BasicPermission {
// Purpose of InternalAccess is to give classes in jdk.jfr.internal
// access to package private methods in this package (jdk.jfr).
//
// The initialization could be done in any class in this package,
// but this one was chosen because it is light weight and
// lacks dependencies on other public classes.
static {
PrivateAccess.setPrivateAccess(new InternalAccess());
}
private final static class InternalAccess extends PrivateAccess {
@Override
public Type getType(Object o) {
if (o instanceof AnnotationElement) {
return ((AnnotationElement) o).getType();
}
if (o instanceof EventType) {
return ((EventType) o).getType();
}
if (o instanceof ValueDescriptor) {
return ((ValueDescriptor) o).getType();
}
if (o instanceof SettingDescriptor) {
return ((SettingDescriptor) o).getType();
}
throw new Error("Unknown type " + o.getClass());
}
@Override
public Configuration newConfiguration(String name, String label, String description, String provider, Map<String, String> settings, String contents) {
return new Configuration(name, label, description, provider, settings, contents);
}
@Override
public EventType newEventType(PlatformEventType platformEventType) {
return new EventType(platformEventType);
}
@Override
public AnnotationElement newAnnotation(Type annotationType, List<Object> values, boolean boot) {
return new AnnotationElement(annotationType, values, boot);
}
@Override
public ValueDescriptor newValueDescriptor(String name, Type fieldType, List<AnnotationElement> annos, int dimension, boolean constantPool, String fieldName) {
return new ValueDescriptor(fieldType, name, annos, dimension, constantPool, fieldName);
}
@Override
public PlatformRecording getPlatformRecording(Recording r) {
return r.getInternal();
}
@Override
public PlatformEventType getPlatformEventType(EventType eventType) {
return eventType.getPlatformEventType();
}
@Override
public boolean isConstantPool(ValueDescriptor v) {
return v.isConstantPool();
}
@Override
public void setAnnotations(ValueDescriptor v, List<AnnotationElement> a) {
v.setAnnotations(a);
}
@Override
public void setAnnotations(SettingDescriptor s, List<AnnotationElement> a) {
s.setAnnotations(a);
}
@Override
public String getFieldName(ValueDescriptor v) {
return v.getJavaFieldName();
}
@Override
public ValueDescriptor newValueDescriptor(Class<?> type, String name) {
return new ValueDescriptor(type, name, Collections.emptyList(), true);
}
@Override
public SettingDescriptor newSettingDescriptor(Type type, String name, String defaultValue, List<AnnotationElement> annotations) {
return new SettingDescriptor(type, name, defaultValue, annotations);
}
@Override
public boolean isUnsigned(ValueDescriptor v) {
return v.isUnsigned();
}
}
/**
* Constructs a {@code FlightRecorderPermission} with the specified name.
*
* @param name permission name, must be either
* {@code "accessFlightRecorder"} or {@code "registerEvent"}, not
* {@code null}
*
* @throws IllegalArgumentException if {@code name} is empty or invalid
*/
public FlightRecorderPermission(String name) {
super(Objects.requireNonNull(name));
if (!name.equals(Utils.ACCESS_FLIGHT_RECORDER) && !name.equals(Utils.REGISTER_EVENT)) {
throw new IllegalArgumentException("name: " + name);
}
}
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation, signifies that the value is a frequency, measured in Hz.
*
* @since 9
*/
@MetadataDefinition
@ContentType
@Label("Frequency")
@Description("Measure of how often something occurs, in Hertz")
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface Frequency {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that sets a human-readable name for an element (for example,
* {@code "Maximum Throughput"}).
* <p>
* Use headline-style capitalization, capitalize the first and last words, and
* all nouns, pronouns, adjectives, verbs and adverbs. Do not include ending
* punctuation.
* <p>
* The label should not be used as an identifier, see {@link Name}.
*
* @since 9
*/
@MetadataDefinition
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Label {
/**
* Returns a human readable name for the annotated element.
*
* @return a human readable name, not {@code null}
*/
String value();
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation, signifies that the value is a memory address.
*
* @since 9
*/
@MetadataDefinition
@ContentType
@Label("Memory Address")
@Description("Represents a physical memory address")
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.METHOD })
public @interface MemoryAddress {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Meta annotation for defining new types of event metadata.
* <p>
* In the following example, a transaction event is defined with two
* user-defined annotations, {@code @Severity} and {@code @TransactionId}.
*
* <pre>
* <code>
*{@literal @}MetadataDefinition
*{@literal @}Label("Severity")
*{@literal @}Description("Value between 0 and 100 that indicates severity. 100 is most severe.")
*{@literal @}Retention(RetentionPolicy.RUNTIME)
*{@literal @}Target({ ElementType.TYPE })
* public {@literal @}interface {@literal @}Severity {
* int value() default 50;
* }
*
*{@literal @}MetadataDefinition
*{@literal @}Label("Transaction Id")
*{@literal @}Relational
*{@literal @}Retention(RetentionPolicy.RUNTIME)
*{@literal @}Target({ ElementType.FIELD })
* public {@literal @}interface {@literal @}Severity {
* }
*
*{@literal @}Severity(80)
*{@literal @}Label("Transaction Blocked");
* class TransactionBlocked extends Event {
* {@literal @}TransactionId
* {@literal @}Label("Transaction");
* long transactionId;
*
* {@literal @}TransactionId
* {@literal @}Label("Transaction Blocker");
* long transactionId;
* }
*
* </code>
* </pre>
*
* Adding {@code @MetadataDefinition} to the declaration of {@code @Severity} and {@code @TransactionId}
* ensures the information is saved by Flight Recorder.
*
* @since 9
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface MetadataDefinition {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that overrides the default name for an element (for example, when
* the default package for an event is not appropriate).
* <p>
* The name must be a valid identifiers in the Java language (for example,
* {@code "com.example.MyEvent"} for an event class or {@code "message"} for an
* event field).
*
* @since 9
*/
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MetadataDefinition
public @interface Name {
/**
* Returns the name.
*
* @return the name
*/
String value();
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation to use on fractions, typically between {@code 0.0}
* and {@code 1.0}, to signify that the value is a percentage.
* <p>
* For example, a field with the value {@code 0.5} annotated by this annotation,
* should be interpreted as {@code 50%} and rendered in a graphical user
* interface with a percentage sign to avoid confusion with {@code 0.005%}.
*
* @since 9
*/
@MetadataDefinition
@ContentType
@Label("Percentage")
@Description("Percentage, represented as a number between 0 and 1")
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface Percentage {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event annotation, specifies the default setting value for a periodic event.
*
* @since 9
*/
@MetadataDefinition
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Target(ElementType.TYPE)
public @interface Period {
/**
* Settings name {@code "period"} for configuring periodic events
*/
public final static String NAME = "period";
/**
* Returns the default setting value for a periodic setting.
* <p>
* String representation of a positive {@code Long} value followed by an empty
* space and one of the following units:<br>
* <br>
* {@code "ns"} (nanoseconds)<br>
* {@code "us"} (microseconds)<br>
* {@code "ms"} (milliseconds)<br>
* {@code "s"} (seconds)<br>
* {@code "m"} (minutes)<br>
* {@code "h"} (hours)<br>
* {@code "d"} (days)<br>
* <p>
* Example values: {@code "0 ns"}, {@code "10 ms"}, and {@code "1 s"}.
* <p>
* A period may also bes <code>"everyChunk"</code> to specify that it occurs at
* least once for every recording file. The number of events that are emitted
* depends on how many times the file rotations occur when data is recorded.
*
* @return the default setting value, not {@code null}
*/
String value() default "everyChunk";
}
此差异已折叠。
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
/**
* Indicates a state in the life cycle of a recording.
*
* @since 9
*/
public enum RecordingState {
/**
* The initial state when a {@code Recording} is created.
*/
NEW,
/**
* The recording is scheduled to start with a start time in the future. An
* invocation of the {@link Recording#start()} method will transition the
* recording into the {@code RUNNING} state.
*/
DELAYED,
/**
* The recording is recording data and an invocation of the {@link Recording#stop()}
* method will transition the recording to the {@code STOPPED} state.
*/
RUNNING,
/**
* The recording is stopped and is holding recorded data that can be dumped to
* disk. An invocation of the {@link Recording#close()} method will release the
* data and transition the recording into the {@code CLOSED} state.
*/
STOPPED,
/**
* The recording is closed and all resources that are associated with the
* recording are released. Nothing that can be done with it from this point, and it's
* no longer retrievable from the {@code FlightRrecorder.getRecordings()} method.
*/
CLOSED;
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event annotation, for programmatic event registration.
* <p>
* Events are automatically registered when they are first used. This annotation
* can be used to override that registration. To register
* events programmatically, use {@link FlightRecorder#register(Class)}.
*
* @since 9
*/
@Target({ ElementType.TYPE })
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Registered {
/**
* Returns {@code true} if the event is to be registered when the event class is
* first used, {@code false} otherwise.
*
* @return {@code true} if the event is to be registered when the event class is
* first used, {@code false} otherwise.
*/
public boolean value() default true;
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Meta annotation for relational annotations, to be used on annotation.
*
* @since 9
*/
@MetadataDefinition
@Label("Relation")
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Relational {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.security.AccessController;
import java.util.Set;
import jdk.jfr.internal.Control;
/**
* Base class to extend to create setting controls.
* <p>
* The following example shows a naive implementation of a setting control for
* regular expressions:
*
* <pre>
* <code>
* final class RegExpControl extends SettingControl {
* private Pattern pattern = Pattern.compile(".*");
*
* {@literal @}Override
* public void setValue(String value) {
* this.pattern = Pattern.compile(value);
* }
*
* {@literal @}Override
* public String combine(Set{@literal <}String{@literal >} values) {
* return String.join("|", values);
* }
*
* {@literal @}Override
* public String getValue() {
* return pattern.toString();
* }
*
* public String matches(String s) {
* return pattern.matcher(s).find();
* }
* }
* </code>
* </pre>
*
* The {@code setValue(String)}, {@code getValue()} and
* {@code combine(Set<String>)} methods are invoked when a setting value
* changes, which typically happens when a recording is started or stopped. The
* {@code combine(Set<String>)} method is invoked to resolve what value to use
* when multiple recordings are running at the same time.
* <p>
* The setting control must have a default constructor that can be invoked when
* the event is registered.
* <p>
* To use a setting control with an event, add a method that returns a
* {@code boolean} value and takes the setting control as a parameter. Annotate
* the method with the {@code @SettingDefinition} annotation. By default, the
* method name is used as the setting name, but the name can be set explicitly
* bby using the {@code @Name} annotation. If the method returns {@code true},
* the event will be committed.
* <p>
* It is recommended that the {@code setValue(String)} method updates an
* efficient data structure that can be quickly checked when the event is
* committed.
* <p>
* Example,
*
* <pre>
* <code>
* abstract class HTTPRequest extends Event {
* {@literal @}Label("Request URI")
* protected String uri;
*
* {@literal @}Label("Servlet URI Filter")
* {@literal @}SettingDefinition
* protected boolean uriFilter(RegExpControl regExp) {
* return regExp.matches(uri);
* }
* }
*
* {@literal @}Label("HTTP Get Request")
* class HTTPGetRequest extends HTTPRequest {
* }
*
* {@literal @}Label("HTTP Post Request")
* class HTTPPostRequest extends HTTPRequest {
* }
*
* class ExampleServlet extends HTTPServlet {
* protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
* HTTPGetRequest request = new HTTPGetRequest();
* request.begin();
* request.uri = req.getRequestURI();
* ...
* request.commit();
* }
*
* protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
* HTTPPostRequest request = new HTTPPostRequest();
* request.begin();
* request.uri = req.getRequestURI();
* ...
* request.commit();
* }
* }
* </code>
* </pre>
*
* The following examples show how an event can be filtered by assigning the
* {@code "uriFilter"} setting with the specified regular expressions, in a
* configuration file or programmatically.
*
* <pre>
* <code>
* Recording r = new Recording();
* r.enable("HTTPGetRequest").with("uriFilter", "https://www.example.com/list/.*");
* r.enable("HTTPPostRequest").with("uriFilter", "https://www.example.com/login/.*");
* r.start();
* </code>
* </pre>
*
*
*
* @see SettingDefinition
*
* @since 9
*/
@MetadataDefinition
public abstract class SettingControl extends Control {
/**
* Constructor for invocation by subclass constructors.
*/
protected SettingControl() {
super(AccessController.getContext());
}
/**
* Combines the setting values for all running recordings into one value when
* multiple recordings are running at the same time,
* <p>
* The semantics of how setting values are combined depends on the setting
* control that is implemented, but all recordings should get at least all the
* events they request..
* <p>
* This method should have no side effects, because the caller might cache values.
* This method should never return {@code null} or throw an exception. If a
* value is not valid for this setting control, the value should be ignored.
* <p>
* Examples:
* <p>
* if the setting control represents a threshold and three recordings are
* running at the same time with the setting values {@code "10 ms"},
* {@code "8 s"}, and {@code "1 ms"}, this method returns {@code "1 ms"}
* because it means that all recordings get at least all the requested data.
* <p>
* If the setting control represents a set of names and two recordings are
* running at the same time with the setting values "Smith, Jones" and "Jones,
* Williams" the returned value is "Smith, Jones, Williams" because all names would be accepted.
* <p>
* If the setting control represents a boolean condition and four recordings are
* running at the same time with the following values "true", "false", "false", and
* "incorrect", this method returns "true", because all
* recordings get at least all the requested data.
*
* @param settingValues the set of values, not {@code null}
*
* @return the value to use, not {@code null}
*/
@Override
public abstract String combine(Set<String> settingValues);
/**
* Sets the value for this setting.
* <p>
* If the setting value is not valid for this setting, this method
* should not throw an exception. Instead, the value is ignored.
*
* @param settingValue the string value, not {@code null}
*/
@Override
public abstract void setValue(String settingValue);
/**
* Returns the currently used value for this setting, not {@code null}.
* <p>
* The value returned by this method should be valid as an argument to both
* the {@code setValue(String)} method and {@code combine(Set)} method.
* <p>
* This method is invoked when an event is registered to obtain the
* default value. It is therefore important that a valid value can be
* returned immediately after an instance of this class is created. It is
* not valid to return {@code null}.
*
* @return the setting value, not {@code null}
*/
@Override
public abstract String getValue();
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that signifies that a method in an event class should be used to
* filter out events.
* <p>
* For the method to be valid it must return a {@code SettingControl} and only have one
* parameter, which should be a non-abstract subclass of {@link SettingControl}
* <p>
* The return value of the method specifies whether the event is to be
* written to the Flight Recorder system or not.
* <p>
* Example.
*
* <pre>
* <code>
* class HelloWorld extend Event {
*
* {@literal @}Label("Message");
* String message;
*
* {@literal @}SettingDefinition;
* {@literal @}Label("Message Filter");
* public boolean filter(RegExpControl regExp) {
* return regExp.matches(message);
* }
* }
* </code>
* </pre>
*
* For an example of how the setting controls are defined, see
* {@link SettingControl}.
*
* @see SettingControl
*
* @since 9
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface SettingDefinition {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import jdk.jfr.internal.AnnotationConstruct;
import jdk.jfr.internal.Type;
/**
* Describes an event setting.
*
* @since 9
*/
public final class SettingDescriptor {
private final AnnotationConstruct annotationConstruct;
private final Type type;
private final String name;
private final String defaultValue;
// package private, invoked by jdk.internal.
SettingDescriptor(Type type, String name, String defaultValue, List<AnnotationElement> annotations) {
Objects.requireNonNull(annotations);
this.name = Objects.requireNonNull(name, "Name of value descriptor can't be null");
this.type = Objects.requireNonNull(type);
this.annotationConstruct = new AnnotationConstruct(annotations);
this.defaultValue = Objects.requireNonNull(defaultValue);
}
// package private
void setAnnotations(List<AnnotationElement> as) {
annotationConstruct.setAnnotationElements(as);
}
/**
* Returns the name of the setting (for example, {@code "threshold"}).
*
* @return the name, not {@code null}
*/
public String getName() {
return name;
}
/**
* Returns a human-readable name that describes the setting (for example,
* {@code "Threshold"}).
* <p>
* If the setting lacks a label, the label for the type that is associated with this
* setting is returned, or {@code null} if not available.
*
* @return a human-readable name, or {@code null} if not available
*/
public String getLabel() {
String label = annotationConstruct.getLabel();
if (label == null) {
label = type.getLabel();
}
return label;
}
/**
* Returns a sentence that describes the setting (for example
* {@code "Record event with duration
* above or equal to threshold"}).
* <p>
* If the setting lacks a description, the description for the type that is
* associated with this setting is returned, or {@code null} if not available.
*
* @return the description, or {@code null} if not available
*/
public String getDescription() {
String description = annotationConstruct.getDescription();
if (description == null) {
description = type.getDescription();
}
return description;
}
/**
* Returns a textual identifier that specifies how a value that is represented by
* this {@link SettingDescriptor} object is interpreted or formatted.
* <p>
* For example, if the setting descriptor represents a percentage, then
* {@code "jdk.jfr.Percentage"} hints to a client that a value of "0.5"
* is formatted as "50%".
* <p>
* The JDK provides the following predefined content types:
* <ul>
* <li>jdk.jfr.Percentage</li>
* <li>jdk.jfr.Timespan</li>
* <li>jdk.jfr.Timestamp</li>
* <li>jdk.jfr.Frequency</li>
* <li>jdk.jfr.Flag</li>
* <li>jdk.jfr.MemoryAddress</li>
* <li>jdk.jfr.DataAmount</li>
* <li>jdk.jfr.NetworkAddress</li>
* </ul>
* <p>
* User-defined content types can be created by using {@link ContentType}.
* <p>
* If the setting lacks a content type, the content type for the type
* that is associated with this setting is returned, or {@code null} if not
* available.
*
* @return the content type, or {@code null} if not available
*
* @see ContentType
*/
public String getContentType() {
for (AnnotationElement anno : getAnnotationElements()) {
for (AnnotationElement meta : anno.getAnnotationElements()) {
if (meta.getTypeName().equals(ContentType.class.getName())) {
return anno.getTypeName();
}
}
}
for (AnnotationElement anno : type.getAnnotationElements()) {
for (AnnotationElement meta : anno.getAnnotationElements()) {
if (meta.getTypeName().equals(ContentType.class.getName())) {
return anno.getTypeName();
}
}
}
return null;
}
/**
* Returns the fully qualified class name of the type that is associated with this
* setting descriptor.
*
* @return the type name, not {@code null}
*
* @see SettingDescriptor#getTypeId()
*/
public String getTypeName() {
return type.getName();
}
/**
* Returns a unique identifier for the type in the Java Virtual Machine (JVM).
*
* The ID might not be the same between JVM instances.
*
* @return the type ID, not negative
*/
public long getTypeId() {
return type.getId();
}
/**
* Returns the first annotation for the specified type if an annotation
* element with the same name is available, {@code null} otherwise.
*
* @param <A> the type of the annotation to query for and return if available
* @param annotationType the Class object that corresponds to the annotation
* type, not {@code null}
* @return this element's annotation for the specified annotation type if
* available, {@code null} otherwise
*/
public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
Objects.requireNonNull(annotationType);
return annotationConstruct.getAnnotation(annotationType);
}
/**
* Returns an immutable list of annotation elements for this value
* descriptor.
*
* @return a list of annotations, not {@code null}
*/
public List<AnnotationElement> getAnnotationElements() {
return Collections.unmodifiableList(annotationConstruct.getUnmodifiableAnnotationElements());
}
/**
* Returns the default value for this setting descriptor.
*
* @return the default value, not {@code null}
*/
public String getDefaultValue() {
return defaultValue;
}
// package private
Type getType() {
return type;
}
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event annotation, determines whether an event by default has a stack trace
* or not.
*
* @since 9
*/
@MetadataDefinition
@Target({ ElementType.TYPE })
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface StackTrace {
/**
* Settings name "stackTrace" to be used for enabling event stack traces.
*/
public final static String NAME = "stackTrace";
/**
* Returns if the stack trace from the commit method should be recorded.
*
* @return {@code true} if the stack trace should be recorded, {@code false}
* otherwise
*/
boolean value() default true;
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event annotation, specifies the duration below which an event is
* not recorded (for example, {@code "20 ms"}).
*
* @since 9
*/
@MetadataDefinition
@Target({ ElementType.TYPE })
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Threshold {
/**
* Setting name {@code "threshold"} for configuring event thresholds.
*/
public final static String NAME = "threshold";
/**
* The threshold (for example, {@code "20 ms"})s.
* <p>
* A string representation of a positive {@code Long} value followed by an
* empty space and one of the following units:<br>
* <br>
* {@code "ns"} (nanoseconds)<br>
* {@code "us"} (microseconds)<br>
* {@code "ms"} (milliseconds)<br>
* {@code "s"} (seconds)<br>
* {@code "m"} (minutes)<br>
* {@code "h"} (hours)<br>
* {@code "d"} (days)<br>
* <p>
* Example values are {@code "0 ns"}, {@code "10 ms"}, and {@code "1 s"}.
*
* @return the threshold, default {@code "0 ns"}, not {@code null}
*/
String value() default "0 ns";
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation, signifies that the value is a duration.
*
* @since 9
*/
@MetadataDefinition
@ContentType
@Label("Timespan")
@Description("A duration, measured in nanoseconds by default")
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface Timespan {
/**
* Unit for ticks.
*/
public static final String TICKS = "TICKS";
/**
* Unit for seconds.
*/
public static final String SECONDS = "SECONDS";
/**
* Unit for milliseconds.
*/
public static final String MILLISECONDS = "MILLISECONDS";
/**
* Unit for nanoseconds.
*/
public static final String NANOSECONDS = "NANOSECONDS";
/**
* Unit for microseconds.
*/
public static final String MICROSECONDS = "MICROSECONDS";
/**
* Returns the unit of measure for the time span. By default, the unit is nanoseconds.
*
* @return the time span unit, default {@code #NANOSECONDS}, not {@code null}
*/
String value() default NANOSECONDS;
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation, signifies that the value is a point in time.
*
* @since 9
*/
@MetadataDefinition
@ContentType
@Label("Timestamp")
@Description("A point in time")
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface Timestamp {
/**
* The unit for the difference, measured in milliseconds, between the current
* time and midnight, January 1, 1970 UTC.
*/
public final static String MILLISECONDS_SINCE_EPOCH = "MILLISECONDS_SINCE_EPOCH";
/**
* The unit for the number of ticks that have transpired since some arbitrary
* starting date.
*/
public final static String TICKS = "TICKS";
/**
* Unit for the time stamp.
*
* @return time-stamp unit, not {@code null}
*/
String value() default Timestamp.MILLISECONDS_SINCE_EPOCH;
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation, signifies that the event transitioned from a thread.
*
* @since 9
*/
@MetadataDefinition
@Label("Transition From")
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TransitionFrom {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation, signifies that the event will soon to transition to a thread.
*
* @since 9
*/
@MetadataDefinition
@Label("Transition To")
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TransitionTo {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Event field annotation, signifies that the value is of an unsigned data type.
*
* @since 9
*/
@MetadataDefinition
@ContentType
@Label("Unsigned Value")
@Description("Value should be interpreted as unsigned data type")
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.TYPE })
public @interface Unsigned {
}
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr.consumer;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import jdk.jfr.EventType;
import jdk.jfr.internal.LogLevel;
import jdk.jfr.internal.LogTag;
import jdk.jfr.internal.Logger;
import jdk.jfr.internal.MetadataDescriptor;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.consumer.ChunkHeader;
import jdk.jfr.internal.consumer.RecordingInput;
/**
* Parses a chunk.
*
*/
final class ChunkParser {
private static final long CONSTANT_POOL_TYPE_ID = 1;
private final RecordingInput input;
private final LongMap<Parser> parsers;
private final ChunkHeader chunkHeader;
private final long absoluteChunkEnd;
private final MetadataDescriptor metadata;
private final LongMap<Type> typeMap;
private final TimeConverter timeConverter;
public ChunkParser(RecordingInput input) throws IOException {
this(new ChunkHeader(input));
}
private ChunkParser(ChunkHeader header) throws IOException {
this.input = header.getInput();
this.chunkHeader = header;
this.metadata = header.readMetadata();
this.absoluteChunkEnd = header.getEnd();
this.timeConverter = new TimeConverter(chunkHeader);
ParserFactory factory = new ParserFactory(metadata, timeConverter);
LongMap<ConstantMap> constantPools = factory.getConstantPools();
parsers = factory.getParsers();
typeMap = factory.getTypeMap();
fillConstantPools(parsers, constantPools);
constantPools.forEach(ConstantMap::setIsResolving);
constantPools.forEach(ConstantMap::resolve);
constantPools.forEach(ConstantMap::setResolved);
input.position(chunkHeader.getEventStart());
}
public RecordedEvent readEvent() throws IOException {
while (input.position() < absoluteChunkEnd) {
long pos = input.position();
int size = input.readInt();
if (size == 0) {
throw new IOException("Event can't have zero size");
}
long typeId = input.readLong();
if (typeId > CONSTANT_POOL_TYPE_ID) { // also skips metadata (id=0)
Parser ep = parsers.get(typeId);
if (ep instanceof EventParser) {
return (RecordedEvent) ep.parse(input);
}
}
input.position(pos + size);
}
return null;
}
private void fillConstantPools(LongMap<Parser> typeParser, LongMap<ConstantMap> constantPools) throws IOException {
long nextCP = chunkHeader.getAbsoluteChunkStart();
long deltaToNext = chunkHeader.getConstantPoolPosition();
while (deltaToNext != 0) {
nextCP += deltaToNext;
input.position(nextCP);
final long position = nextCP;
int size = input.readInt(); // size
long typeId = input.readLong();
if (typeId != CONSTANT_POOL_TYPE_ID) {
throw new IOException("Expected check point event (id = 1) at position " + nextCP + ", but found type id = " + typeId);
}
input.readLong(); // timestamp
input.readLong(); // duration
deltaToNext = input.readLong();
final long delta = deltaToNext;
boolean flush = input.readBoolean();
int poolCount = input.readInt();
Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.TRACE, () -> {
return "New constant pool: startPosition=" + position +
", size=" + size + ", deltaToNext=" + delta +
", flush=" + flush + ", poolCount=" + poolCount;
});
for (int i = 0; i < poolCount; i++) {
long id = input.readLong(); // type id
ConstantMap pool = constantPools.get(id);
Type type = typeMap.get(id);
if (pool == null) {
Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found constant pool(" + id + ") that is never used");
if (type == null) {
throw new IOException("Error parsing constant pool type " + getName(id) + " at position " + input.position() + " at check point between [" + nextCP + ", " + nextCP + size + "]");
}
pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type.getName());
constantPools.put(type.getId(), pool);
}
Parser parser = typeParser.get(id);
if (parser == null) {
throw new IOException("Could not find constant pool type with id = " + id);
}
try {
int count = input.readInt();
Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.TRACE, () -> "Constant: " + getName(id) + "[" + count + "]");
for (int j = 0; j < count; j++) {
long key = input.readLong();
Object value = parser.parse(input);
pool.put(key, value);
}
} catch (Exception e) {
throw new IOException("Error parsing constant pool type " + getName(id) + " at position " + input.position() + " at check point between [" + nextCP + ", " + nextCP + size + "]", e);
}
}
if (input.position() != nextCP + size) {
throw new IOException("Size of check point event doesn't match content");
}
}
}
private String getName(long id) {
Type type = typeMap.get(id);
return type == null ? ("unknown(" + id +")") : type.getName();
}
public Collection<Type> getTypes() {
return metadata.getTypes();
}
public List<EventType> getEventTypes() {
return metadata.getEventTypes();
}
public boolean isLastChunk() {
return chunkHeader.isLastChunk();
}
public ChunkParser nextChunkParser() throws IOException {
return new ChunkParser(chunkHeader.nextHeader());
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册