8326838: JFR: Native mirror events

Reviewed-by: mgronlun
This commit is contained in:
Erik Gahlin 2024-02-29 20:18:17 +00:00
parent b8fc4186d5
commit d29cefb6eb
4 changed files with 58 additions and 11 deletions

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
@ -35,12 +35,14 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import jdk.jfr.AnnotationElement;
import jdk.jfr.Event;
import jdk.jfr.EventType;
import jdk.jfr.Name;
import jdk.jfr.Period;
import jdk.jfr.StackTrace;
import jdk.jfr.Threshold;
@ -54,8 +56,8 @@ public final class MetadataRepository {
private static final MetadataRepository instance = new MetadataRepository();
private final List<EventType> nativeEventTypes = new ArrayList<>(150);
private final List<EventControl> nativeControls = new ArrayList<EventControl>(nativeEventTypes.size());
private final Map<String, EventType> nativeEventTypes = LinkedHashMap.newHashMap(150);
private final Map<String, EventControl> nativeControls = LinkedHashMap.newHashMap(150);
private final SettingsManager settingsManager = new SettingsManager();
private Constructor<EventConfiguration> cachedEventConfigurationConstructor;
private boolean staleMetadata = true;
@ -83,8 +85,9 @@ public final class MetadataRepository {
PeriodicEvents.addJVMEvent(pEventType);
}
}
nativeControls.add(new EventControl(pEventType));
nativeEventTypes.add(eventType);
String name = eventType.getName();
nativeControls.put(name, new EventControl(pEventType));
nativeEventTypes.put(name,eventType);
}
}
}
@ -101,7 +104,7 @@ public final class MetadataRepository {
eventTypes.add(ec.getEventType());
}
}
for (EventType t : nativeEventTypes) {
for (EventType t : nativeEventTypes.values()) {
if (PrivateAccess.getInstance().isVisible(t)) {
eventTypes.add(t);
}
@ -200,6 +203,32 @@ public final class MetadataRepository {
if (pEventType == null) {
pEventType = (PlatformEventType) TypeLibrary.createType(eventClass, dynamicAnnotations, dynamicFields);
}
// Check for native mirror.
// Note, defining an event in metadata.xml is not a generic mechanism to emit
// native data in Java. For example, calling JVM.getStackTraceId(int, long)
// and assign the result to a long field is not enough to always get a proper
// stack trace. Purpose of the mechanism is to transfer metadata, such as
// native type IDs, without specialized Java logic for each type.
if (eventClass.getClassLoader() == null) {
Name name = eventClass.getAnnotation(Name.class);
if (name != null) {
String n = name.value();
EventType nativeType = nativeEventTypes.get(n);
if (nativeType != null) {
var nativeFields = nativeType.getFields();
var eventFields = pEventType.getFields();
var comparator = Comparator.comparing(ValueDescriptor::getName);
if (!Utils.compareLists(nativeFields, eventFields, comparator)) {
throw new InternalError("Field for native mirror event " + n + " doesn't match Java event");
}
nativeEventTypes.remove(n);
nativeControls.remove(n);
TypeLibrary.removeType(nativeType.getId());
pEventType.setAnnotations(nativeType.getAnnotationElements());
pEventType.setFields(nativeType.getFields());
}
}
}
EventType eventType = PrivateAccess.getInstance().newEventType(pEventType);
EventControl ec = new EventControl(pEventType, eventClass);
EventConfiguration configuration = newEventConfiguration(eventType, ec);
@ -226,7 +255,7 @@ public final class MetadataRepository {
public synchronized List<EventControl> getEventControls() {
List<Class<? extends jdk.internal.event.Event>> eventClasses = JVM.getAllEventClasses();
ArrayList<EventControl> controls = new ArrayList<>(eventClasses.size() + nativeControls.size());
controls.addAll(nativeControls);
controls.addAll(nativeControls.values());
for (Class<? extends jdk.internal.event.Event> clazz : eventClasses) {
EventConfiguration eh = JVMSupport.getConfiguration(clazz);
if (eh != null) {

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
@ -222,6 +222,10 @@ public class Type implements Comparable<Type> {
return id < JVM.RESERVED_CLASS_ID_LIMIT;
}
public void setFields(List<ValueDescriptor> fields) {
this.fields = List.copyOf(fields);
}
public void add(ValueDescriptor valueDescriptor) {
Objects.requireNonNull(valueDescriptor);
fields.add(valueDescriptor);

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
@ -322,7 +322,7 @@ public final class TypeLibrary {
ValueDescriptor vd = dynamicFieldSet.get(field.getName());
if (vd != null) {
if (!vd.getTypeName().equals(field.getType().getName())) {
throw new InternalError("Type expected to match for field " + vd.getName() + " expected " + field.getName() + " but got " + vd.getName());
throw new InternalError("Type expected to match for field " + vd.getName() + " expected " + field.getType().getName() + " but got " + vd.getTypeName());
}
for (AnnotationElement ae : vd.getAnnotationElements()) {
newTypes.add(PrivateAccess.getInstance().getType(ae));

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
@ -37,6 +37,7 @@ import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -176,6 +177,19 @@ public final class Utils {
return map;
}
public static <T> boolean compareLists(List<T> a, List<T> b, Comparator<T> c) {
int size = a.size();
if (size != b.size()) {
return false;
}
for (int i = 0; i < size; i++) {
if (c.compare(a.get(i), b.get(i)) != 0) {
return false;
}
}
return true;
}
public static <T> List<T> sanitizeNullFreeList(List<T> elements, Class<T> clazz) {
List<T> sanitized = new ArrayList<>(elements.size());
for (T element : elements) {