8330734: JFR: Re-engineer mirror class mechanism

Reviewed-by: mgronlun
This commit is contained in:
Erik Gahlin 2024-04-26 17:15:09 +00:00
parent 0bf516f7ba
commit 07facd0420
26 changed files with 128 additions and 160 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2024, 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
@ -36,9 +36,8 @@ import jdk.jfr.internal.RemoveFields;
@Label("Deserialization")
@Name("jdk.Deserialization")
@Description("Results of deserialization and ObjectInputFilter checks")
@MirrorEvent(className = "jdk.internal.event.DeserializationEvent")
@RemoveFields("duration")
public final class DeserializationEvent extends AbstractJDKEvent {
public final class DeserializationEvent extends MirrorEvent {
@Label("Filter Configured")
public boolean filterConfigured;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024, 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
@ -36,9 +36,8 @@ import jdk.jfr.internal.Type;
@Label("Java Error")
@Category("Java Application")
@Description("An object derived from java.lang.Error has been created. OutOfMemoryErrors are ignored")
@MirrorEvent(className = "jdk.internal.event.ErrorThrownEvent")
@RemoveFields("duration")
public final class ErrorThrownEvent extends AbstractJDKEvent {
public final class ErrorThrownEvent extends MirrorEvent {
@Label("Message")
public String message;

View File

@ -31,14 +31,15 @@ import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
import jdk.jfr.internal.MirrorEvent;
import jdk.jfr.internal.RemoveFields;
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")
@MirrorEvent(className = "jdk.internal.event.ExceptionStatisticsEvent")
public final class ExceptionStatisticsEvent extends AbstractPeriodicEvent {
@RemoveFields({"duration", "eventThread", "stackTrace"})
public final class ExceptionStatisticsEvent extends MirrorEvent {
@Label("Exceptions Created")
public long throwables;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024, 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
@ -37,9 +37,8 @@ import jdk.jfr.internal.Type;
@Label("Java Exception")
@Category("Java Application")
@Description("An object derived from java.lang.Exception has been created")
@MirrorEvent(className = "jdk.internal.event.ExceptionThrownEvent")
@RemoveFields("duration")
public final class ExceptionThrownEvent extends AbstractJDKEvent {
public final class ExceptionThrownEvent extends MirrorEvent {
@Label("Message")
public String message;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2024, 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
@ -36,10 +36,9 @@ import jdk.jfr.internal.RemoveFields;
@Label("Process Start")
@Name("jdk.ProcessStart")
@Description("Operating system process started")
@MirrorEvent(className = "jdk.internal.event.ProcessStartEvent")
@RemoveFields("duration")
@StackFilter({"java.lang.ProcessBuilder", "java.lang.Runtime::exec"})
public final class ProcessStartEvent extends AbstractJDKEvent {
public final class ProcessStartEvent extends MirrorEvent {
@Label("Process Id")
public long pid;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, 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
@ -33,10 +33,9 @@ import jdk.jfr.internal.RemoveFields;
@Label("Security Property Modification")
@Name("jdk.SecurityPropertyModification")
@Description("Modification of Security property")
@MirrorEvent(className = "jdk.internal.event.SecurityPropertyModificationEvent")
@RemoveFields("duration")
@StackFilter({"java.security.Security::setProperty"})
public final class SecurityPropertyModificationEvent extends AbstractJDKEvent {
public final class SecurityPropertyModificationEvent extends MirrorEvent {
@Label("Key")
public String key;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, 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
@ -36,10 +36,9 @@ import jdk.jfr.internal.RemoveFields;
@Label("Security Provider Instance Request")
@Name("jdk.SecurityProviderService")
@Description("Details of Provider.getInstance(String type, String algorithm) calls")
@MirrorEvent(className = "jdk.internal.event.SecurityProviderServiceEvent")
@RemoveFields("duration")
@StackFilter({"java.security.Provider::getService"})
public final class SecurityProviderServiceEvent extends AbstractJDKEvent {
public final class SecurityProviderServiceEvent extends MirrorEvent {
@Label("Type of Service")
public String type;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024, 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
@ -40,9 +40,8 @@ import jdk.jfr.internal.Type;
" The checks are usually performed just once per serializable class," +
" the first time it is used by serialization." +
" Under high memory pressure, a class might be re-checked again.")
@MirrorEvent(className = "jdk.internal.event.SerializationMisdeclarationEvent")
@RemoveFields({"duration", "stackTrace", "eventThread"})
public final class SerializationMisdeclarationEvent extends AbstractJDKEvent {
public final class SerializationMisdeclarationEvent extends MirrorEvent {
@Label("Misdeclared Class")
public Class<?> misdeclaredClass;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024, 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
@ -38,8 +38,7 @@ import jdk.jfr.internal.Type;
@Label("Socket Read")
@Category("Java Application")
@Description("Reading data from a socket")
@MirrorEvent(className = "jdk.internal.event.SocketReadEvent")
public final class SocketReadEvent extends AbstractJDKEvent {
public final class SocketReadEvent extends MirrorEvent {
@Label("Remote Host")
public String host;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024, 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
@ -37,8 +37,7 @@ import jdk.jfr.internal.Type;
@Label("Socket Write")
@Category("Java Application")
@Description("Writing data to a socket")
@MirrorEvent(className = "jdk.internal.event.SocketWriteEvent")
public final class SocketWriteEvent extends AbstractJDKEvent {
public final class SocketWriteEvent extends MirrorEvent {
@Label("Remote Host")
public String host;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, 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
@ -37,10 +37,9 @@ import jdk.jfr.internal.RemoveFields;
@Label("TLS Handshake")
@Name("jdk.TLSHandshake")
@Description("Parameters used in TLS Handshake")
@MirrorEvent(className = "jdk.internal.event.TLSHandshakeEvent")
@RemoveFields("duration")
@StackFilter("sun.security.ssl.Finished::recordEvent")
public final class TLSHandshakeEvent extends AbstractJDKEvent {
public final class TLSHandshakeEvent extends MirrorEvent {
@Label("Peer Host")
public String peerHost;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2024, 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
@ -34,11 +34,10 @@ import jdk.jfr.internal.MirrorEvent;
@Category("Java Application")
@Label("Java Thread Sleep")
@Name("jdk.ThreadSleep")
@MirrorEvent(className = "jdk.internal.event.ThreadSleepEvent")
@StackFilter({"java.lang.Thread::afterSleep",
"java.lang.Thread::sleepNanos",
"java.lang.Thread::sleep"})
public final class ThreadSleepEvent extends AbstractJDKEvent {
public final class ThreadSleepEvent extends MirrorEvent {
@Label("Sleep Time")
@Timespan(Timespan.NANOSECONDS)
public long time;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2024, 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
@ -34,9 +34,8 @@ import jdk.jfr.internal.RemoveFields;
@Category("Java Application")
@Label("Virtual Thread End")
@Name("jdk.VirtualThreadEnd")
@MirrorEvent(className = "jdk.internal.event.VirtualThreadEndEvent")
@RemoveFields({"duration", "stackTrace"})
public final class VirtualThreadEndEvent extends AbstractJDKEvent {
public final class VirtualThreadEndEvent extends MirrorEvent {
@Label("Thread Id")
public long javaThreadId;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2024, 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
@ -33,6 +33,5 @@ import jdk.jfr.internal.MirrorEvent;
@Category("Java Application")
@Label("Virtual Thread Pinned")
@Name("jdk.VirtualThreadPinned")
@MirrorEvent(className = "jdk.internal.event.VirtualThreadPinnedEvent")
public final class VirtualThreadPinnedEvent extends AbstractJDKEvent {
public final class VirtualThreadPinnedEvent extends MirrorEvent {
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2024, 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
@ -34,9 +34,8 @@ import jdk.jfr.internal.RemoveFields;
@Category("Java Application")
@Label("Virtual Thread Start")
@Name("jdk.VirtualThreadStart")
@MirrorEvent(className = "jdk.internal.event.VirtualThreadStartEvent")
@RemoveFields("duration")
public final class VirtualThreadStartEvent extends AbstractJDKEvent {
public final class VirtualThreadStartEvent extends MirrorEvent {
@Label("Thread Id")
public long javaThreadId;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2024, 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
@ -36,9 +36,8 @@ import jdk.jfr.internal.RemoveFields;
@Label("Virtual Thread Submit Failed")
@Name("jdk.VirtualThreadSubmitFailed")
@Description("Submit of task for virtual thread failed")
@MirrorEvent(className = "jdk.internal.event.VirtualThreadSubmitFailedEvent")
@RemoveFields("duration")
public final class VirtualThreadSubmitFailedEvent extends AbstractJDKEvent {
public final class VirtualThreadSubmitFailedEvent extends MirrorEvent {
@Label("Thread Id")
public long javaThreadId;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, 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
@ -33,9 +33,8 @@ import jdk.jfr.internal.RemoveFields;
@Label("X509 Certificate")
@Name("jdk.X509Certificate")
@Description("Details of X.509 Certificate parsed by JDK")
@MirrorEvent(className = "jdk.internal.event.X509CertificateEvent")
@RemoveFields("duration")
public final class X509CertificateEvent extends AbstractJDKEvent {
public final class X509CertificateEvent extends MirrorEvent {
@Label("Signature Algorithm")
public String algorithm;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2024, 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
@ -33,9 +33,8 @@ import jdk.jfr.internal.RemoveFields;
@Label("X509 Validation")
@Name("jdk.X509Validation")
@Description("Serial numbers from X.509 Certificates forming chain of trust")
@MirrorEvent(className = "jdk.internal.event.X509ValidationEvent")
@RemoveFields("duration")
public final class X509ValidationEvent extends AbstractJDKEvent {
public final class X509ValidationEvent extends MirrorEvent {
@CertificateId
@Label("Certificate Id")
@Unsigned

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, 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
@ -90,7 +90,6 @@ final class EventInstrumentation {
private static final ClassDesc TYPE_ISE = Bytecode.classDesc(IllegalStateException.class);
private static final ClassDesc TYPE_EVENT_WRITER = classDesc(EventWriter.class);
private static final ClassDesc TYPE_EVENT_WRITER_FACTORY = ClassDesc.of("jdk.jfr.internal.event.EventWriterFactory");
private static final ClassDesc TYPE_MIRROR_EVENT = Bytecode.classDesc(MirrorEvent.class);
private static final ClassDesc TYPE_OBJECT = Bytecode.classDesc(Object.class);
private static final ClassDesc TYPE_SETTING_DEFINITION = Bytecode.classDesc(SettingDefinition.class);
private static final MethodDesc METHOD_BEGIN = MethodDesc.of("begin", "()V");
@ -144,9 +143,7 @@ final class EventInstrumentation {
private ImplicitFields determineImplicitFields() {
if (isJDK) {
// For now, only support mirror events in java.base
String fullName = "java.base:" + className;
Class<?> eventClass = MirrorEvents.find(fullName);
Class<?> eventClass = MirrorEvents.find(isJDK, className);
if (eventClass != null) {
return new ImplicitFields(eventClass);
}
@ -221,20 +218,6 @@ final class EventInstrumentation {
return true;
}
boolean isMirrorEvent() {
String typeDescriptor = TYPE_MIRROR_EVENT.descriptorString();
for (ClassElement ce : classModel.elements()) {
if (ce instanceof RuntimeVisibleAnnotationsAttribute rvaa) {
for (var annotation : rvaa.annotations()) {
if (annotation.className().equalsString(typeDescriptor)) {
return true;
}
}
}
}
return false;
}
@SuppressWarnings("unchecked")
// Only supports String, String[] and Boolean values
private static <T> T annotationValue(ClassModel classModel, ClassDesc classDesc, Class<T> type) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, 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
@ -112,9 +112,6 @@ final class JVMUpcalls {
Logger.log(LogTag.JFR_SYSTEM, LogLevel.INFO, "Skipping instrumentation for " + eventName + " since container support is missing");
return oldBytes;
}
if (ei.isMirrorEvent()) {
return oldBytes;
}
if (!forceInstrumentation) {
// Assume we are recording

View File

@ -144,10 +144,6 @@ public final class MetadataRepository {
}
EventConfiguration configuration = getConfiguration(eventClass, true);
if (configuration == null) {
if (eventClass.getAnnotation(MirrorEvent.class) != null) {
// Don't register mirror classes.
return null;
}
PlatformEventType pe = findMirrorType(eventClass);
configuration = makeConfiguration(eventClass, pe, dynamicAnnotations, dynamicFields);
}
@ -162,8 +158,7 @@ public final class MetadataRepository {
}
private PlatformEventType findMirrorType(Class<? extends jdk.internal.event.Event> eventClass) throws InternalError {
String fullName = eventClass.getModule().getName() + ":" + eventClass.getName();
Class<? extends Event> mirrorClass = MirrorEvents.find(fullName);
Class<? extends MirrorEvent> mirrorClass = MirrorEvents.find(eventClass);
if (mirrorClass == null) {
return null; // not a mirror
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, 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
@ -22,32 +22,28 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr.internal;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;
/**
* Any event class annotated with this annotation must be added
* to the {@link MirrorEvents) class for it to take effect.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface MirrorEvent {
/**
* Fully qualified name of the class to mirror metadata for (for example,
* {@code "jdk.internal.event.Example"})
*
* @return the fully qualified class name of the event
*/
String className();
import jdk.jfr.Enabled;
import jdk.jfr.Registered;
import jdk.jfr.StackTrace;
/**
* The module where the event is located, by default {@code "java.base"}.
*
* @return the module name
*/
String module() default "java.base";
/**
* A mirror event is a fictitious event class that contains metadata about an
* event, but not the implementation to write the event data to buffers.
* <p>
* A mirror event should be used when an event class is in a module where a
* dependency on the jdk.jfr module is not possible, for example, due to a
* circular dependency.
* <p>
* Subclass the MirrorEvent class and add the exact same fields as the actual
* event, but with labels, descriptions etc.
* <p>
* For the mirror mechanism to work, the mirror class must be registered in the
* jdk.jfr.internal.MirrorEvents class.
*/
@Registered(false)
@Enabled(false)
@StackTrace(false)
public abstract class MirrorEvent {
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, 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
@ -24,10 +24,9 @@
*/
package jdk.jfr.internal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import jdk.jfr.Event;
import jdk.jfr.events.DeserializationEvent;
import jdk.jfr.events.ErrorThrownEvent;
import jdk.jfr.events.ExceptionStatisticsEvent;
@ -47,52 +46,46 @@ import jdk.jfr.events.VirtualThreadSubmitFailedEvent;
import jdk.jfr.events.X509CertificateEvent;
import jdk.jfr.events.X509ValidationEvent;
public final class MirrorEvents {
private static final Class<?>[] mirrorEventClasses = {
DeserializationEvent.class,
ProcessStartEvent.class,
SecurityPropertyModificationEvent.class,
SecurityProviderServiceEvent.class,
SerializationMisdeclarationEvent.class,
SocketReadEvent.class,
SocketWriteEvent.class,
ThreadSleepEvent.class,
TLSHandshakeEvent.class,
VirtualThreadStartEvent.class,
VirtualThreadEndEvent.class,
VirtualThreadPinnedEvent.class,
VirtualThreadSubmitFailedEvent.class,
X509CertificateEvent.class,
X509ValidationEvent.class,
ErrorThrownEvent.class,
ExceptionStatisticsEvent.class,
ExceptionThrownEvent.class,
/**
* This class registers all mirror events.
*/
final class MirrorEvents {
private static final Map<String, Class<? extends MirrorEvent>> mirrorLookup = new ConcurrentHashMap<>();
// Add mirror event mapping here. See MirrorEvent class for details.
static {
register("jdk.internal.event.DeserializationEvent", DeserializationEvent.class);
register("jdk.internal.event.ProcessStartEvent", ProcessStartEvent.class);
register("jdk.internal.event.SecurityPropertyModificationEvent", SecurityPropertyModificationEvent.class);
register("jdk.internal.event.SecurityProviderServiceEvent", SecurityProviderServiceEvent.class);
register("jdk.internal.event.SerializationMisdeclarationEvent", SerializationMisdeclarationEvent.class);
register("jdk.internal.event.SocketReadEvent", SocketReadEvent.class);
register("jdk.internal.event.SocketWriteEvent", SocketWriteEvent.class);
register("jdk.internal.event.ThreadSleepEvent", ThreadSleepEvent.class);
register("jdk.internal.event.TLSHandshakeEvent", TLSHandshakeEvent.class);
register("jdk.internal.event.VirtualThreadStartEvent", VirtualThreadStartEvent.class);
register("jdk.internal.event.VirtualThreadEndEvent", VirtualThreadEndEvent.class);
register("jdk.internal.event.VirtualThreadPinnedEvent", VirtualThreadPinnedEvent.class);
register("jdk.internal.event.VirtualThreadSubmitFailedEvent", VirtualThreadSubmitFailedEvent.class);
register("jdk.internal.event.X509CertificateEvent", X509CertificateEvent.class);
register("jdk.internal.event.X509ValidationEvent", X509ValidationEvent.class);
register("jdk.internal.event.ErrorThrownEvent", ErrorThrownEvent.class);
register("jdk.internal.event.ExceptionStatisticsEvent", ExceptionStatisticsEvent.class);
register("jdk.internal.event.ExceptionThrownEvent", ExceptionThrownEvent.class);
};
private static final Map<String, Class<? extends Event>> mirrorLookup = createLookup();
private static void register(String eventClassName, Class<? extends MirrorEvent> mirrorClass) {
mirrorLookup.put(eventClassName, mirrorClass);
}
public static Class<? extends Event> find(String name) {
// When <clinit> of this class is executed it may lead
// to a JVM up call and invocation of this method before
// the mirrorLookup field has been set. This is fine,
// mirrors should not be instrumented.
if (mirrorLookup != null) {
static Class<? extends MirrorEvent> find(Class<? extends jdk.internal.event.Event> eventClass) {
return find(eventClass.getClassLoader() == null, eventClass.getName());
}
static Class<? extends MirrorEvent> find(boolean bootClassLoader, String name) {
if (bootClassLoader) {
return mirrorLookup.get(name);
}
return null;
}
@SuppressWarnings("unchecked")
private static Map<String, Class<? extends Event>> createLookup() {
Map<String, Class<? extends Event>> mirrors = new HashMap<>();
for (Class<?> eventClass : mirrorEventClasses) {
MirrorEvent me = eventClass.getAnnotation(MirrorEvent.class);
if (me == null) {
throw new InternalError("Mirror class must have annotation " + MirrorEvent.class.getName());
}
String fullName = me.module() + ":" + me.className();
mirrors.put(fullName, (Class<? extends Event>) eventClass);
}
return mirrors;
}
}

View File

@ -263,7 +263,7 @@ public final class TypeLibrary {
// STRUCT
String superType = null;
boolean eventType = false;
if (jdk.internal.event.Event.class.isAssignableFrom(clazz)) {
if (isEventClass(clazz)) {
superType = Type.SUPER_TYPE_EVENT;
eventType= true;
}
@ -291,6 +291,16 @@ public final class TypeLibrary {
return type;
}
private static boolean isEventClass(Class<?> clazz) {
if (jdk.internal.event.Event.class.isAssignableFrom(clazz)) {
return true;
}
if (MirrorEvent.class.isAssignableFrom(clazz)) {
return true;
}
return false;
}
private static void addAnnotations(Class<?> clazz, Type type, List<AnnotationElement> dynamicAnnotations) {
ArrayList<AnnotationElement> aes = new ArrayList<>();
if (dynamicAnnotations.isEmpty()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024, 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
@ -41,11 +41,11 @@ public final class ImplicitFields {
private final List<String> fields = new ArrayList<>(4);
public ImplicitFields(Class<?> eventClass) {
fields.add(START_TIME); // for completeness, not really needed
fields.add(START_TIME);
fields.add(DURATION);
fields.add(STACK_TRACE);
fields.add(EVENT_THREAD);
for (Class<?> c = eventClass; jdk.internal.event.Event.class != c; c = c.getSuperclass()) {
for (Class<?> c = eventClass; !Utils.isEventBaseClass(c); c = c.getSuperclass()) {
RemoveFields rf = c.getAnnotation(RemoveFields.class);
if (rf != null) {
for (String value : rf.value()) {

View File

@ -51,6 +51,7 @@ import jdk.jfr.RecordingState;
import jdk.jfr.internal.LogLevel;
import jdk.jfr.internal.LogTag;
import jdk.jfr.internal.Logger;
import jdk.jfr.internal.MirrorEvent;
import jdk.jfr.internal.SecuritySupport;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.settings.PeriodSetting;
@ -206,9 +207,8 @@ public final class Utils {
}
public static List<Field> getVisibleEventFields(Class<?> clazz) {
Utils.ensureValidEventSubclass(clazz);
List<Field> fields = new ArrayList<>();
for (Class<?> c = clazz; c != jdk.internal.event.Event.class; c = c.getSuperclass()) {
for (Class<?> c = clazz; !Utils.isEventBaseClass(c); c = c.getSuperclass()) {
for (Field field : c.getDeclaredFields()) {
// skip private field in base classes
if (c == clazz || !Modifier.isPrivate(field.getModifiers())) {
@ -219,6 +219,16 @@ public final class Utils {
return fields;
}
public static boolean isEventBaseClass(Class<?> clazz) {
if (jdk.internal.event.Event.class == clazz) {
return true;
}
if (jdk.jfr.internal.MirrorEvent.class == clazz) {
return true;
}
return false;
}
public static void ensureValidEventSubclass(Class<?> eventClass) {
if (jdk.internal.event.Event.class.isAssignableFrom(eventClass) && Modifier.isAbstract(eventClass.getModifiers())) {
throw new IllegalArgumentException("Abstract event classes are not allowed");
@ -338,7 +348,7 @@ public final class Utils {
return eventName;
}
public static void verifyMirror(Class<?> mirror, Class<?> real) {
public static void verifyMirror(Class<? extends MirrorEvent> mirror, Class<?> real) {
Class<?> cMirror = Objects.requireNonNull(mirror);
Class<?> cReal = Objects.requireNonNull(real);
@ -353,7 +363,7 @@ public final class Utils {
}
while (cReal != null) {
for (Field realField : cReal.getDeclaredFields()) {
if (isSupportedType(realField.getType())) {
if (isSupportedType(realField.getType()) && !realField.isSynthetic()) {
String fieldName = realField.getName();
Field mirrorField = mirrorFields.get(fieldName);
if (mirrorField == null) {