Skip to content

Commit

Permalink
8326838: JFR: Native mirror events
Browse files Browse the repository at this point in the history
Reviewed-by: mgronlun
  • Loading branch information
egahlin committed Feb 29, 2024
1 parent b8fc418 commit d29cefb
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 11 deletions.
43 changes: 36 additions & 7 deletions src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -35,12 +35,14 @@
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;
Expand All @@ -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;
Expand Down Expand Up @@ -83,8 +85,9 @@ private void initializeJVMEventTypes() {
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);
}
}
}
Expand All @@ -101,7 +104,7 @@ public synchronized List<EventType> getRegisteredEventTypes() {
eventTypes.add(ec.getEventType());
}
}
for (EventType t : nativeEventTypes) {
for (EventType t : nativeEventTypes.values()) {
if (PrivateAccess.getInstance().isVisible(t)) {
eventTypes.add(t);
}
Expand Down Expand Up @@ -200,6 +203,32 @@ private EventConfiguration makeConfiguration(Class<? extends jdk.internal.event.
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);
Expand All @@ -226,7 +255,7 @@ synchronized void disableEvents() {
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) {
Expand Down
6 changes: 5 additions & 1 deletion src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -222,6 +222,10 @@ public boolean isDefinedByJVM() {
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);
Expand Down
4 changes: 2 additions & 2 deletions src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -322,7 +322,7 @@ private static void addUserFields(Class<?> clazz, Type type, List<ValueDescripto
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));
Expand Down
16 changes: 15 additions & 1 deletion src/jdk.jfr/share/classes/jdk/jfr/internal/util/Utils.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -37,6 +37,7 @@
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;
Expand Down Expand Up @@ -176,6 +177,19 @@ public static Map<String, String> sanitizeNullFreeStringMap(Map<String, String>
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) {
Expand Down

1 comment on commit d29cefb

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.