# HG changeset patch # User egahlin # Date 1586255267 -7200 # Tue Apr 07 12:27:47 2020 +0200 # Node ID 4888ec761c69030195d675cfcb1690f83e0d9c38 # Parent f2a0b262efea0d28f7041bdb4874cf92f02897f8 fields_april.txt diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/AbstractJDKEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/AbstractJDKEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/AbstractJDKEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/AbstractJDKEvent.java @@ -33,5 +33,6 @@ @Registered(false) @Enabled(false) @StackTrace(false) +@DefaultFields(duration=true, eventThread=true, stackTrace=true) abstract class AbstractJDKEvent extends Event { } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java @@ -26,10 +26,9 @@ package jdk.jfr.events; import jdk.jfr.Category; +import jdk.jfr.DataAmount; import jdk.jfr.Label; -import jdk.jfr.DataAmount; import jdk.jfr.Name; -import jdk.jfr.StackTrace; import jdk.jfr.Timespan; import jdk.jfr.Timestamp; import jdk.jfr.internal.Type; @@ -37,7 +36,7 @@ @Name(Type.EVENT_NAME_PREFIX + "ActiveRecording") @Label("Flight Recording") @Category("Flight Recorder") -@StackTrace(false) +@DefaultFields(duration=false, eventThread=false, stackTrace=false) public final class ActiveRecordingEvent extends AbstractJDKEvent { public static final ThreadLocal EVENT = new ThreadLocal() { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java @@ -28,13 +28,12 @@ import jdk.jfr.Category; import jdk.jfr.Label; import jdk.jfr.Name; -import jdk.jfr.StackTrace; import jdk.jfr.internal.Type; @Name(Type.EVENT_NAME_PREFIX + "ActiveSetting") @Label("Recording Setting") @Category("Flight Recorder") -@StackTrace(false) +@DefaultFields(duration=false, eventThread=false, stackTrace=false) public final class ActiveSettingEvent extends AbstractJDKEvent { public static final ThreadLocal EVENT = new ThreadLocal() { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/DefaultFields.java b/src/jdk.jfr/share/classes/jdk/jfr/events/DefaultFields.java new file mode 100644 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/DefaultFields.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, 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.events; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Inherited +@Retention(RUNTIME) +@Target(TYPE) +public @interface DefaultFields { + /** + * If the event should allow the thread to be recorded. + * + * @return true if the thread should be allowed, false otherwise + */ + boolean eventThread() default true; + + /** + * If the event should allow an event to be timed using the + * {@code Event#begin()} and {@code Event#end()} method. + * + * @return true if the duration should be allowed, false otherwise + */ + boolean duration() default true; + + /** + * If the event should allow a stack trace to be recorded. + * + * @return true if a stack trace should be allowed, false otherwise + */ + boolean stackTrace() default true; +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ErrorThrownEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ErrorThrownEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ErrorThrownEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ErrorThrownEvent.java @@ -34,6 +34,7 @@ @Label("Java Error") @Category("Java Application") @Description("An object derived from java.lang.Error has been created. OutOfMemoryErrors are ignored") +@DefaultFields(duration=false, eventThread=true, stackTrace=true) public final class ErrorThrownEvent extends AbstractJDKEvent { @Label("Message") diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java @@ -29,14 +29,13 @@ import jdk.jfr.Description; import jdk.jfr.Label; import jdk.jfr.Name; -import jdk.jfr.StackTrace; import jdk.jfr.internal.Type; @Name(Type.EVENT_NAME_PREFIX + "ExceptionStatistics") @Label("Exception Statistics") @Category({ "Java Application", "Statistics" }) @Description("Number of objects derived from java.lang.Throwable that have been created") -@StackTrace(false) +@DefaultFields(duration=false, eventThread=false, stackTrace=false) public final class ExceptionStatisticsEvent extends AbstractJDKEvent { @Label("Exceptions Created") diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionThrownEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionThrownEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionThrownEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionThrownEvent.java @@ -35,6 +35,7 @@ @Label("Java Exception") @Category("Java Application") @Description("An object derived from java.lang.Exception has been created") +@DefaultFields(duration=false, eventThread=true, stackTrace=true) public final class ExceptionThrownEvent extends AbstractJDKEvent { @Label("Message") diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ProcessStartEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ProcessStartEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/ProcessStartEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ProcessStartEvent.java @@ -36,6 +36,7 @@ @Name("jdk.ProcessStart") @Description("Operating system process started") @MirrorEvent(className = "jdk.internal.event.ProcessStartEvent") +@DefaultFields(duration=false, eventThread=true, stackTrace=true) public final class ProcessStartEvent extends AbstractJDKEvent { @Label("Process Id") public long pid; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/SecurityPropertyModificationEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/SecurityPropertyModificationEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/SecurityPropertyModificationEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/SecurityPropertyModificationEvent.java @@ -33,6 +33,7 @@ @Name("jdk.SecurityPropertyModification") @Description("Modification of Security property") @MirrorEvent(className = "jdk.internal.event.SecurityPropertyModificationEvent") +@DefaultFields(duration=false, eventThread=true, stackTrace=true) public final class SecurityPropertyModificationEvent extends AbstractJDKEvent { @Label("Key") public String key; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/TLSHandshakeEvent.java @@ -36,6 +36,7 @@ @Name("jdk.TLSHandshake") @Description("Parameters used in TLS Handshake") @MirrorEvent(className = "jdk.internal.event.TLSHandshakeEvent") +@DefaultFields(duration=false, eventThread=true, stackTrace=true) public final class TLSHandshakeEvent extends AbstractJDKEvent { @Label("Peer Host") public String peerHost; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/X509CertificateEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/X509CertificateEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/X509CertificateEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/X509CertificateEvent.java @@ -33,6 +33,7 @@ @Name("jdk.X509Certificate") @Description("Details of X.509 Certificate parsed by JDK") @MirrorEvent(className = "jdk.internal.event.X509CertificateEvent") +@DefaultFields(duration=false, eventThread=true, stackTrace=true) public final class X509CertificateEvent extends AbstractJDKEvent { @Label("Signature Algorithm") public String algorithm; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/X509ValidationEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/X509ValidationEvent.java --- a/src/jdk.jfr/share/classes/jdk/jfr/events/X509ValidationEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/X509ValidationEvent.java @@ -33,6 +33,7 @@ @Name("jdk.X509Validation") @Description("Serial numbers from X.509 Certificates forming chain of trust") @MirrorEvent(className = "jdk.internal.event.X509ValidationEvent") +@DefaultFields(duration=false, eventThread=true, stackTrace=true) public final class X509ValidationEvent extends AbstractJDKEvent { @CertificateId @Label("Certificate Id") diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ASMToolkit.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ASMToolkit.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ASMToolkit.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ASMToolkit.java @@ -139,7 +139,8 @@ StringBuilder sb = new StringBuilder(); sb.append("("); for (FieldInfo v : fields) { - if (!v.fieldName.equals(EventInstrumentation.FIELD_EVENT_THREAD) && !v.fieldName.equals(EventInstrumentation.FIELD_STACK_TRACE)) { + if (!v.fieldName.equals(EventInstrumentation.FIELD_EVENT_THREAD) + && !v.fieldName.equals(EventInstrumentation.FIELD_STACK_TRACE)) { sb.append(v.fieldDescriptor); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventHandlerCreator.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventHandlerCreator.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventHandlerCreator.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventHandlerCreator.java @@ -43,6 +43,7 @@ import jdk.jfr.EventType; import jdk.jfr.SettingControl; import jdk.jfr.ValueDescriptor; +import jdk.jfr.internal.EventInstrumentation.DefaultFieldsInfo; import jdk.jfr.internal.EventInstrumentation.FieldInfo; import jdk.jfr.internal.EventInstrumentation.SettingInfo; import jdk.jfr.internal.handlers.EventHandler; @@ -80,21 +81,26 @@ private final String internalClassName; private final List settingInfos; private final List fields; + private final DefaultFieldsInfo defaultFieldsInfo; - public EventHandlerCreator(long id, List settingInfos, List fields) { + private String debugName; + + public EventHandlerCreator(String debugName, long id, DefaultFieldsInfo dfi, List settingInfos, List fields) { this.classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); this.className = makeEventHandlerName(id); this.internalClassName = ASMToolkit.getInternalName(className); this.settingInfos = settingInfos; this.fields = fields; + this.defaultFieldsInfo = dfi; + this.debugName = debugName; } public static String makeEventHandlerName(long id) { return EventHandler.class.getName() + id + SUFFIX; } - public EventHandlerCreator(long id, List settingInfos, EventType type, Class eventClass) { - this(id, settingInfos, createFieldInfos(eventClass, type)); + public EventHandlerCreator(String debugName, long id, DefaultFieldsInfo dfi, List settingInfos, EventType type, Class eventClass) { + this(debugName, id, dfi, settingInfos, createFieldInfos(eventClass, type)); } private static List createFieldInfos(Class eventClass, EventType type) throws Error { @@ -214,6 +220,12 @@ int slotIndex = 1; // indexes the proper slot in the local variable table, takes type size into account, therefore sometimes argIndex != slotIndex int fieldIndex = 0; Method desc = ASMToolkit.makeWriteMethod(fields); + System.out.println("Handler: " + debugName); + System.out.println("Fields:" + fields); + System.out.println("has thread:" + defaultFieldsInfo.hasThread); + System.out.println("has stack trace:" + defaultFieldsInfo.hasStackTrace); + System.out.println("has duration:" + defaultFieldsInfo.hasDuration); + System.out.println(); Type[] argumentTypes = Type.getArgumentTypes(desc.getDescriptor()); MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC, desc.getName(), desc.getDescriptor(), null, null); mv.visitCode(); @@ -246,23 +258,36 @@ // stack: [BW] fieldIndex++; // write duration - mv.visitInsn(Opcodes.DUP); - // stack: [BW], [BW] - mv.visitVarInsn(argumentTypes[argIndex].getOpcode(Opcodes.ILOAD), slotIndex); - // stack: [BW], [BW], [long] - slotIndex += argumentTypes[argIndex++].getSize(); - visitMethod(mv, Opcodes.INVOKEVIRTUAL, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.asASM()); - // stack: [BW] - fieldIndex++; - // write eventThread - mv.visitInsn(Opcodes.DUP); - // stack: [BW], [BW] - visitMethod(mv, Opcodes.INVOKEVIRTUAL, TYPE_EVENT_WRITER, EventWriterMethod.PUT_EVENT_THREAD.asASM()); - // stack: [BW] - // write stackTrace - mv.visitInsn(Opcodes.DUP); - // stack: [BW], [BW] - visitMethod(mv, Opcodes.INVOKEVIRTUAL, TYPE_EVENT_WRITER, EventWriterMethod.PUT_STACK_TRACE.asASM()); + if (defaultFieldsInfo.hasDuration) { + mv.visitInsn(Opcodes.DUP); + // stack: [BW], [BW] + mv.visitVarInsn(argumentTypes[argIndex].getOpcode(Opcodes.ILOAD), slotIndex); + // stack: [BW], [BW], [long] + slotIndex += argumentTypes[argIndex++].getSize(); + visitMethod(mv, Opcodes.INVOKEVIRTUAL, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.asASM()); + fieldIndex++; + } +/* System.out.println(debugName); + System.out.println("fieldIndex:" + fieldIndex); + int i = 0; + for (FieldInfo f : fields) { + System.out.println(i + ":" + f.fieldName); + } + System.out.println("hasThread: " + defaultFieldsInfo.hasThread); + System.out.println("hasStackTrace: " + defaultFieldsInfo.hasStackTrace); + System.out.println();*/ + if (defaultFieldsInfo.hasThread) { + // stack: [BW] + mv.visitInsn(Opcodes.DUP); + // stack: [BW], [BW] + visitMethod(mv, Opcodes.INVOKEVIRTUAL, TYPE_EVENT_WRITER, EventWriterMethod.PUT_EVENT_THREAD.asASM()); + } + if (defaultFieldsInfo.hasStackTrace) { + // stack: [BW] + mv.visitInsn(Opcodes.DUP); + // stack: [BW], [BW] + visitMethod(mv, Opcodes.INVOKEVIRTUAL, TYPE_EVENT_WRITER, EventWriterMethod.PUT_STACK_TRACE.asASM()); + } // stack: [BW] // write custom fields while (fieldIndex < fields.size()) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java @@ -51,6 +51,7 @@ import jdk.jfr.Registered; import jdk.jfr.SettingControl; import jdk.jfr.SettingDefinition; +import jdk.jfr.events.DefaultFields; import jdk.jfr.internal.handlers.EventHandler; /** @@ -58,6 +59,30 @@ * */ public final class EventInstrumentation { + + public static final class DefaultFieldsInfo { + final boolean hasThread; + final boolean hasStackTrace; + final boolean hasDuration; + public DefaultFieldsInfo(boolean hasStackTrace, boolean hasThread, boolean hasDuration) { + this.hasStackTrace = hasStackTrace; + this.hasThread = hasThread; + this.hasDuration = hasDuration; + } + public DefaultFieldsInfo(Class clazz) { + DefaultFields df = clazz.getAnnotation(DefaultFields.class); + if (df == null) { + this.hasThread = true; + this.hasDuration = true; + this.hasStackTrace = true; + } else { + this.hasThread = df.eventThread(); + this.hasDuration = df.duration(); + this.hasStackTrace = df.stackTrace(); + } + } + } + static final class SettingInfo { private String methodName; private String internalSettingName; @@ -88,6 +113,10 @@ public boolean isString() { return STRING.getDescriptor().equals(fieldDescriptor); } + + public String toString() { + return fieldName; + } } public static final String FIELD_EVENT_THREAD = "eventThread"; @@ -100,6 +129,7 @@ private static final Type ANNOTATION_TYPE_NAME = Type.getType(Name.class); private static final Type ANNOTATION_TYPE_REGISTERED = Type.getType(Registered.class); private static final Type ANNOTATION_TYPE_ENABLED = Type.getType(Enabled.class); + private static final Type ANNOTATION_TYPE_DEFAULT_FIELDS = Type.getType(DefaultFields.class); private static final Type TYPE_EVENT_HANDLER = Type.getType(EventHandler.class); private static final Type TYPE_SETTING_CONTROL = Type.getType(SettingControl.class); private static final Type TYPE_OBJECT = Type.getType(Object.class); @@ -119,19 +149,22 @@ private final String eventHandlerXInternalName; private final String eventName; private final boolean untypedEventHandler; + private final DefaultFieldsInfo defaultFields; + private final Class superClass; + private boolean guardHandlerReference; - private Class superClass; EventInstrumentation(Class superClass, byte[] bytes, long id) { this.superClass = superClass; this.classNode = createClassNode(bytes); - this.settingInfos = buildSettingInfos(superClass, classNode); - this.fieldInfos = buildFieldInfos(superClass, classNode); + String n = annotationValue(ANNOTATION_TYPE_NAME, "value", String.class); + this.eventName = n == null ? classNode.name.replace("/", ".") : n; + this.defaultFields = buildDefaultFields(); + this.settingInfos = buildSettingInfos(); + this.fieldInfos = buildFieldInfos(); this.untypedEventHandler = hasUntypedHandler(); + this.eventHandlerXInternalName = ASMToolkit.getInternalName(EventHandlerCreator.makeEventHandlerName(id)); this.writeMethod = makeWriteMethod(fieldInfos); - this.eventHandlerXInternalName = ASMToolkit.getInternalName(EventHandlerCreator.makeEventHandlerName(id)); - String n = annotationValue(classNode, ANNOTATION_TYPE_NAME.getDescriptor(), String.class); - this.eventName = n == null ? classNode.name.replace("/", ".") : n; } private boolean hasUntypedHandler() { @@ -143,6 +176,24 @@ throw new InternalError("Class missing handler field"); } + DefaultFieldsInfo getDefaultFieldsInfo() { + return this.defaultFields; + } + + private DefaultFieldsInfo buildDefaultFields() { + Boolean stackTrace = annotationBoolean(ANNOTATION_TYPE_DEFAULT_FIELDS, "stackTrace"); + Boolean thread = annotationBoolean(ANNOTATION_TYPE_DEFAULT_FIELDS, "eventThread"); + Boolean duration = annotationBoolean(ANNOTATION_TYPE_DEFAULT_FIELDS, "duration"); + System.out.println(eventName + " buildDefaultFields: " + stackTrace + " " + thread + " " + duration); + if (stackTrace != null && thread != null && duration != null) { + return new DefaultFieldsInfo(stackTrace, thread, duration); + } + if (superClass != null) { + return new DefaultFieldsInfo(superClass); + } + return new DefaultFieldsInfo(true, true, true); + } + public String getClassName() { return classNode.name.replace("/","."); } @@ -155,7 +206,7 @@ } boolean isRegistered() { - Boolean result = annotationValue(classNode, ANNOTATION_TYPE_REGISTERED.getDescriptor(), Boolean.class); + Boolean result = annotationBoolean(ANNOTATION_TYPE_REGISTERED, "value"); if (result != null) { return result.booleanValue(); } @@ -168,8 +219,9 @@ return true; } + boolean isEnabled() { - Boolean result = annotationValue(classNode, ANNOTATION_TYPE_ENABLED.getDescriptor(), Boolean.class); + Boolean result = annotationBoolean(ANNOTATION_TYPE_ENABLED, "value"); if (result != null) { return result.booleanValue(); } @@ -182,20 +234,27 @@ return true; } + private Boolean annotationBoolean(Type aType, String name) { + return annotationValue(aType, name, Boolean.class); + } + @SuppressWarnings("unchecked") - private static T annotationValue(ClassNode classNode, String typeDescriptor, Class type) { + private T annotationValue(Type aType, String name, Class type) { + String typeDescriptor = aType.getDescriptor(); if (classNode.visibleAnnotations != null) { for (AnnotationNode a : classNode.visibleAnnotations) { if (typeDescriptor.equals(a.desc)) { List values = a.values; - if (values != null && values.size() == 2) { - Object key = values.get(0); - Object value = values.get(1); - if (key instanceof String && value != null) { - if (type == value.getClass()) { - String keyName = (String) key; - if ("value".equals(keyName)) { - return (T) value; + if (values != null) { + for (int i = 0; i< values.size(); i+=2) { + Object key = values.get(i); + Object value = values.get(i + 1); + if (key instanceof String && value != null) { + if (type == value.getClass()) { + String keyName = (String) key; + if (name.equals(keyName)) { + return (T) value; + } } } } @@ -206,7 +265,7 @@ return null; } - private static List buildSettingInfos(Class superClass, ClassNode classNode) { + private List buildSettingInfos() { Set methodSet = new HashSet<>(); List settingInfos = new ArrayList<>(); String settingDescriptor = Type.getType(SettingDefinition.class).getDescriptor(); @@ -262,7 +321,7 @@ return settingInfos; } - private static List buildFieldInfos(Class superClass, ClassNode classNode) { + private List buildFieldInfos() { Set fieldSet = new HashSet<>(); List fieldInfos = new ArrayList<>(classNode.fields.size()); // These two field are added by native as transient so they will be @@ -272,7 +331,10 @@ // in Java, instead of in native. It also means code for adding implicit // fields for native can be reused by Java. fieldInfos.add(new FieldInfo("startTime", Type.LONG_TYPE.getDescriptor(), classNode.name)); - fieldInfos.add(new FieldInfo("duration", Type.LONG_TYPE.getDescriptor(), classNode.name)); + System.out.println("buildFieldInfo: hasDuration=" + defaultFields.hasDuration); + if (defaultFields.hasDuration) { + fieldInfos.add(new FieldInfo("duration", Type.LONG_TYPE.getDescriptor(), classNode.name)); + } for (FieldNode field : classNode.fields) { if (!fieldSet.contains(field.name) && isValidField(field.access, Type.getType(field.desc).getClassName())) { FieldInfo fi = new FieldInfo(field.name, field.desc, classNode.name); @@ -520,14 +582,18 @@ classNode.methods.add(index, newMethod); } - public static Method makeWriteMethod(List fields) { + public Method makeWriteMethod(List fields) { StringBuilder sb = new StringBuilder(); sb.append("("); for (FieldInfo v : fields) { sb.append(v.fieldDescriptor); } sb.append(")V"); - return new Method("write", sb.toString()); + System.out.println("Instrument:" + eventName); + System.out.println("Fields: " + fields); + Method r= new Method("write", sb.toString()); + System.out.println("Method: " + r.getDescriptor()); + return r; } private String getInternalClassName() { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVMUpcalls.java @@ -112,7 +112,7 @@ // guard against a null reference. ei.setGuardHandler(true); Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Adding " + (forceInstrumentation ? "forced " : "") + "instrumentation for event type " + eventName + " during initial class load"); - EventHandlerCreator eh = new EventHandlerCreator(traceId, ei.getSettingInfos(), ei.getFieldInfos()); + EventHandlerCreator eh = new EventHandlerCreator(eventName, traceId, ei.getDefaultFieldsInfo(), ei.getSettingInfos(), ei.getFieldInfos()); // Handler class must be loaded before instrumented event class can // be used eh.makeEventHandlerClass(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataHandler.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataHandler.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataHandler.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataHandler.java @@ -56,6 +56,7 @@ import jdk.jfr.TransitionFrom; import jdk.jfr.TransitionTo; import jdk.jfr.Unsigned; +import jdk.jfr.internal.EventInstrumentation.DefaultFieldsInfo; final class MetadataHandler extends DefaultHandler implements EntityResolver { @@ -261,7 +262,8 @@ Type type = lookup.get(te.name); if (te.isEvent) { boolean periodic = te.period!= null; - TypeLibrary.addImplicitFields(type, periodic, te.startTime && !periodic, te.thread, te.stackTrace && !periodic, te.cutoff); + PlatformEventType pType = (PlatformEventType) type; + TypeLibrary.addImplicitFields(pType, te.cutoff); } for (FieldElement f : te.fields) { Type fieldType = Type.getKnownType(f.typeName); @@ -337,7 +339,10 @@ Type type; if (t.isEvent) { aes.add(new AnnotationElement(Enabled.class, false)); - type = new PlatformEventType(t.name, eventTypeId++, false, true); + boolean periodic = t.period != null; + boolean duration = t.startTime && !periodic; + DefaultFieldsInfo dfi = new DefaultFieldsInfo(t.stackTrace, t.thread, duration); + type = new PlatformEventType(t.name, eventTypeId++, dfi, false, true); } else { // Struct types had their own XML-element in the past. To have id assigned in the // same order as generated .hpp file do some tweaks here. diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java @@ -259,7 +259,7 @@ long id = typeElement.attribute(ATTRIBUTE_ID, -1); Type t; if (Type.SUPER_TYPE_EVENT.equals(superType)) { - t = new PlatformEventType(typeName, id, false, false); + t = new PlatformEventType(typeName, id); } else { t = new Type(typeName, superType, id, false, simpleType); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java @@ -45,6 +45,7 @@ import jdk.jfr.StackTrace; import jdk.jfr.Threshold; import jdk.jfr.ValueDescriptor; +import jdk.jfr.internal.EventInstrumentation.DefaultFieldsInfo; import jdk.jfr.internal.RequestEngine.RequestHook; import jdk.jfr.internal.consumer.RepositoryFiles; import jdk.jfr.internal.handlers.EventHandler; @@ -187,7 +188,7 @@ pEventType.setInstrumented(); Logger.log(JFR_SYSTEM, DEBUG, "Found existing event handler for " + eventType.getName()); } catch (ClassNotFoundException cne) { - EventHandlerCreator ehc = new EventHandlerCreator(eventType.getId(), ec.getSettingInfos(), eventType, eventClass); + EventHandlerCreator ehc = new EventHandlerCreator(eventType.getName(), eventType.getId(), pEventType.getDefaultFields(), ec.getSettingInfos(), eventType, eventClass); handlerClass = ehc.makeEventHandlerClass(); Logger.log(LogTag.JFR_SYSTEM, DEBUG, "Created event handler for " + eventType.getName()); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java @@ -29,7 +29,10 @@ import java.util.List; import java.util.Objects; +import jdk.internal.event.Event; import jdk.jfr.SettingDescriptor; +import jdk.jfr.events.DefaultFields; +import jdk.jfr.internal.EventInstrumentation.DefaultFieldsInfo; /** * Implementation of event type. @@ -44,6 +47,7 @@ private final List settings = new ArrayList<>(5); private final boolean dynamicSettings; private final int stackTraceOffset; + private final DefaultFieldsInfo defaultFieldsInfo; // default values private boolean enabled = false; @@ -65,13 +69,30 @@ // package private - PlatformEventType(String name, long id, boolean isJDK, boolean dynamicSettings) { + PlatformEventType(String name, long id, DefaultFieldsInfo dfi, boolean isJDK, boolean dynamicSettings) { super(name, Type.SUPER_TYPE_EVENT, id); this.dynamicSettings = dynamicSettings; this.isJVM = Type.isDefinedByJVM(id); this.isMethodSampling = isJVM && (name.equals(Type.EVENT_NAME_PREFIX + "ExecutionSample") || name.equals(Type.EVENT_NAME_PREFIX + "NativeMethodSample")); this.isJDK = isJDK; this.stackTraceOffset = stackTraceOffset(name, isJDK); + this.defaultFieldsInfo = dfi; + } + + // Used by parser + public PlatformEventType(String name, long id) { + super(name, Type.SUPER_TYPE_EVENT, id); + // The below values are irrelevant + this.dynamicSettings = false; + this.isJDK = false; + this.isJVM = false; + this.isMethodSampling = false; + this.stackTraceOffset = 0; + this.defaultFieldsInfo = new DefaultFieldsInfo(false, false, false); + } + + DefaultFieldsInfo getDefaultFields() { + return defaultFieldsInfo; } private static int stackTraceOffset(String name, boolean isJDK) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java @@ -47,6 +47,7 @@ import java.util.TimerTask; import java.util.concurrent.CopyOnWriteArrayList; +import jdk.jfr.Event; import jdk.jfr.EventType; import jdk.jfr.FlightRecorder; import jdk.jfr.FlightRecorderListener; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java @@ -56,6 +56,7 @@ import jdk.jfr.Timespan; import jdk.jfr.Timestamp; import jdk.jfr.ValueDescriptor; +import jdk.jfr.internal.EventInstrumentation.DefaultFieldsInfo; public final class TypeLibrary { @@ -197,7 +198,9 @@ long id = Type.getTypeId(clazz); Type t; if (eventType) { - t = new PlatformEventType(typeName, id, clazz.getClassLoader() == null, true); + boolean isJDK = clazz.getClassLoader() == null; + DefaultFieldsInfo dfi = new DefaultFieldsInfo(clazz); + t = new PlatformEventType(typeName, id, dfi, isJDK, true); } else { t = new Type(typeName, superType, id); } @@ -252,7 +255,7 @@ Type type = getType(clazz); if (eventType) { - addImplicitFields(type, true, true, true, true ,false); + addImplicitFields((PlatformEventType)type, false); addUserFields(clazz, type, dynamicFields); type.trimFields(); } @@ -314,23 +317,24 @@ } // By convention all events have these fields. - static void addImplicitFields(Type type, boolean requestable, boolean hasDuration, boolean hasThread, boolean hasStackTrace, boolean hasCutoff) { + static void addImplicitFields(PlatformEventType type, boolean hasCutoff) { createAnnotationType(Timespan.class); createAnnotationType(Timestamp.class); createAnnotationType(Label.class); defineType(long.class, null,false); - addFields(type, requestable, hasDuration, hasThread, hasStackTrace, hasCutoff); + addFields(type, hasCutoff); } - private static void addFields(Type type, boolean requestable, boolean hasDuration, boolean hasThread, boolean hasStackTrace, boolean hasCutoff) { + private static void addFields(PlatformEventType type, boolean hasCutoff) { + DefaultFieldsInfo dfi = type.getDefaultFields(); type.add(START_TIME_FIELD); - if (hasDuration || hasCutoff) { + if (dfi.hasDuration || hasCutoff) { type.add(DURATION_FIELD); } - if (hasThread) { + if (dfi.hasThread) { type.add(THREAD_FIELD); } - if (hasStackTrace) { + if (dfi.hasStackTrace) { type.add(STACK_TRACE_FIELD); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java @@ -109,6 +109,7 @@ RequestEngine.addTrustedJDKHook(ExceptionStatisticsEvent.class, emitExceptionStatistics); } } catch (Exception e) { + e.printStackTrace(); Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not initialize JDK events. " + e.getMessage()); } }