mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-20 21:03:18 +00:00
8303674: JFR: TypeLibrary class not thread safe
Reviewed-by: mgronlun
This commit is contained in:
parent
c26e1d0148
commit
9dd7b87997
@ -57,7 +57,6 @@ public final class MetadataRepository {
|
||||
|
||||
private final List<EventType> nativeEventTypes = new ArrayList<>(150);
|
||||
private final List<EventControl> nativeControls = new ArrayList<EventControl>(nativeEventTypes.size());
|
||||
private final TypeLibrary typeLibrary = TypeLibrary.getInstance();
|
||||
private final SettingsManager settingsManager = new SettingsManager();
|
||||
private final Map<String, Class<? extends Event>> mirrors = new HashMap<>();
|
||||
private Constructor<EventConfiguration> cachedEventConfigurationConstructor;
|
||||
@ -70,7 +69,8 @@ public final class MetadataRepository {
|
||||
}
|
||||
|
||||
private void initializeJVMEventTypes() {
|
||||
for (Type type : new ArrayList<>(typeLibrary.getTypes())) {
|
||||
TypeLibrary.initialize();
|
||||
for (Type type : TypeLibrary.getTypes()) {
|
||||
if (type instanceof PlatformEventType pEventType) {
|
||||
EventType eventType = PrivateAccess.getInstance().newEventType(pEventType);
|
||||
pEventType.setHasDuration(eventType.getAnnotation(Threshold.class) != null);
|
||||
@ -152,7 +152,7 @@ public final class MetadataRepository {
|
||||
configuration = makeConfiguration(eventClass, pe, dynamicAnnotations, dynamicFields);
|
||||
}
|
||||
configuration.getPlatformEventType().setRegistered(true);
|
||||
typeLibrary.addType(configuration.getPlatformEventType());
|
||||
TypeLibrary.addType(configuration.getPlatformEventType());
|
||||
if (jvm.isRecording()) {
|
||||
settingsManager.setEventControl(configuration.getEventControl(), true, JVM.counterTime());
|
||||
settingsManager.updateRetransform(Collections.singletonList((eventClass)));
|
||||
@ -169,7 +169,7 @@ public final class MetadataRepository {
|
||||
}
|
||||
Utils.verifyMirror(mirrorClass, eventClass);
|
||||
PlatformEventType et = (PlatformEventType) TypeLibrary.createType(mirrorClass);
|
||||
typeLibrary.removeType(et.getId());
|
||||
TypeLibrary.removeType(et.getId());
|
||||
long id = Type.getTypeId(eventClass);
|
||||
et.setId(id);
|
||||
return et;
|
||||
@ -260,7 +260,7 @@ public final class MetadataRepository {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(40000);
|
||||
DataOutputStream daos = new DataOutputStream(baos);
|
||||
try {
|
||||
List<Type> types = typeLibrary.getVisibleTypes();
|
||||
List<Type> types = TypeLibrary.getVisibleTypes();
|
||||
if (Logger.shouldLog(LogTag.JFR_METADATA, LogLevel.DEBUG)) {
|
||||
Collections.sort(types,Comparator.comparing(Type::getName));
|
||||
for (Type t: types) {
|
||||
@ -303,7 +303,7 @@ public final class MetadataRepository {
|
||||
}
|
||||
unregisterUnloaded();
|
||||
if (unregistered) {
|
||||
if (typeLibrary.clearUnregistered()) {
|
||||
if (TypeLibrary.clearUnregistered()) {
|
||||
storeDescriptorInJVM();
|
||||
}
|
||||
unregistered = false;
|
||||
@ -320,7 +320,7 @@ public final class MetadataRepository {
|
||||
for (Class<? extends jdk.internal.event.Event> ec: eventClasses) {
|
||||
knownIds.add(Type.getTypeId(ec));
|
||||
}
|
||||
for (Type type : typeLibrary.getTypes()) {
|
||||
for (Type type : TypeLibrary.getTypes()) {
|
||||
if (type instanceof PlatformEventType pe) {
|
||||
if (!knownIds.contains(pe.getId())) {
|
||||
if (!pe.isJVM()) {
|
||||
@ -354,7 +354,7 @@ public final class MetadataRepository {
|
||||
}
|
||||
|
||||
static void unhideInternalTypes() {
|
||||
for (Type t : TypeLibrary.getInstance().getTypes()) {
|
||||
for (Type t : TypeLibrary.getTypes()) {
|
||||
if (t.isInternal()) {
|
||||
t.setVisible(true);
|
||||
Logger.log(LogTag.JFR_METADATA, LogLevel.DEBUG, "Unhiding internal type " + t.getName());
|
||||
@ -367,6 +367,6 @@ public final class MetadataRepository {
|
||||
}
|
||||
|
||||
public synchronized List<Type> getVisibleTypes() {
|
||||
return typeLibrary.getVisibleTypes();
|
||||
return TypeLibrary.getVisibleTypes();
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,21 +60,16 @@ import jdk.jfr.Timestamp;
|
||||
import jdk.jfr.ValueDescriptor;
|
||||
|
||||
public final class TypeLibrary {
|
||||
|
||||
private static TypeLibrary instance;
|
||||
private static boolean implicitFieldTypes;
|
||||
private static final Map<Long, Type> types = LinkedHashMap.newLinkedHashMap(350);
|
||||
|
||||
static final ValueDescriptor DURATION_FIELD = createDurationField();
|
||||
static final ValueDescriptor THREAD_FIELD = createThreadField();
|
||||
static final ValueDescriptor STACK_TRACE_FIELD = createStackTraceField();
|
||||
static final ValueDescriptor START_TIME_FIELD = createStartTimeField();
|
||||
|
||||
private TypeLibrary(List<Type> jvmTypes) {
|
||||
visitReachable(jvmTypes, t -> !types.containsKey(t.getId()), t -> types.put(t.getId(), t));
|
||||
if (Logger.shouldLog(LogTag.JFR_SYSTEM_METADATA, LogLevel.INFO)) {
|
||||
Stream<Type> s = types.values().stream().sorted((x, y) -> Long.compare(x.getId(), y.getId()));
|
||||
s.forEach(t -> t.log("Added", LogTag.JFR_SYSTEM_METADATA, LogLevel.INFO));
|
||||
}
|
||||
private TypeLibrary() {
|
||||
throw new InternalError("Don't instantiate");
|
||||
}
|
||||
|
||||
private static ValueDescriptor createStartTimeField() {
|
||||
@ -82,7 +77,6 @@ public final class TypeLibrary {
|
||||
annos.add(new jdk.jfr.AnnotationElement(Timestamp.class, Timestamp.TICKS));
|
||||
return PrivateAccess.getInstance().newValueDescriptor(EventInstrumentation.FIELD_START_TIME, Type.LONG, annos, 0, false,
|
||||
EventInstrumentation.FIELD_START_TIME);
|
||||
|
||||
}
|
||||
|
||||
private static ValueDescriptor createStackTraceField() {
|
||||
@ -103,28 +97,27 @@ public final class TypeLibrary {
|
||||
return PrivateAccess.getInstance().newValueDescriptor(EventInstrumentation.FIELD_DURATION, Type.LONG, annos, 0, false, EventInstrumentation.FIELD_DURATION);
|
||||
}
|
||||
|
||||
public static TypeLibrary getInstance() {
|
||||
synchronized (TypeLibrary.class) {
|
||||
if (instance == null) {
|
||||
List<Type> jvmTypes;
|
||||
try {
|
||||
jvmTypes = MetadataLoader.createTypes();
|
||||
jvmTypes.sort(Comparator.comparingLong(Type::getId));
|
||||
} catch (IOException e) {
|
||||
throw new Error("JFR: Could not read metadata");
|
||||
}
|
||||
instance = new TypeLibrary(jvmTypes);
|
||||
}
|
||||
return instance;
|
||||
public static synchronized void initialize() {
|
||||
List<Type> jvmTypes;
|
||||
try {
|
||||
jvmTypes = MetadataLoader.createTypes();
|
||||
jvmTypes.sort(Comparator.comparingLong(Type::getId));
|
||||
} catch (IOException e) {
|
||||
throw new Error("JFR: Could not read metadata");
|
||||
}
|
||||
visitReachable(jvmTypes, t -> !types.containsKey(t.getId()), t -> types.put(t.getId(), t));
|
||||
if (Logger.shouldLog(LogTag.JFR_SYSTEM_METADATA, LogLevel.INFO)) {
|
||||
Stream<Type> s = types.values().stream().sorted((x, y) -> Long.compare(x.getId(), y.getId()));
|
||||
s.forEach(t -> t.log("Added", LogTag.JFR_SYSTEM_METADATA, LogLevel.INFO));
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Type> getTypes() {
|
||||
return types.values();
|
||||
public static synchronized Collection<Type> getTypes() {
|
||||
return new ArrayList<>(types.values());
|
||||
}
|
||||
|
||||
// Returned list should be mutable (for in-place sorting)
|
||||
public List<Type> getVisibleTypes() {
|
||||
public static synchronized List<Type> getVisibleTypes() {
|
||||
List<Type> visible = new ArrayList<>(types.size());
|
||||
types.values().forEach(t -> {
|
||||
if (t.isVisible()) {
|
||||
@ -134,7 +127,7 @@ public final class TypeLibrary {
|
||||
return visible;
|
||||
}
|
||||
|
||||
public static Type createAnnotationType(Class<? extends Annotation> a) {
|
||||
public static synchronized Type createAnnotationType(Class<? extends Annotation> a) {
|
||||
if (shouldPersist(a)) {
|
||||
Type type = defineType(a, Type.SUPER_TYPE_ANNOTATION, false);
|
||||
if (type != null) {
|
||||
@ -156,7 +149,7 @@ public final class TypeLibrary {
|
||||
return null;
|
||||
}
|
||||
|
||||
static AnnotationElement createAnnotation(Annotation annotation) {
|
||||
public static synchronized AnnotationElement createAnnotation(Annotation annotation) {
|
||||
Class<? extends Annotation> annotationType = annotation.annotationType();
|
||||
Type type = createAnnotationType(annotationType);
|
||||
if (type != null) {
|
||||
@ -219,11 +212,12 @@ public final class TypeLibrary {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static Type createType(Class<?> clazz) {
|
||||
|
||||
public static synchronized Type createType(Class<?> clazz) {
|
||||
return createType(clazz, Collections.emptyList(), Collections.emptyList());
|
||||
}
|
||||
|
||||
public static Type createType(Class<?> clazz, List<AnnotationElement> dynamicAnnotations, List<ValueDescriptor> dynamicFields) {
|
||||
public static synchronized Type createType(Class<?> clazz, List<AnnotationElement> dynamicAnnotations, List<ValueDescriptor> dynamicFields) {
|
||||
|
||||
if (Thread.class == clazz) {
|
||||
return Type.THREAD;
|
||||
@ -327,7 +321,7 @@ public final class TypeLibrary {
|
||||
}
|
||||
|
||||
// By convention all events have these fields.
|
||||
static void addImplicitFields(Type type, boolean requestable, boolean hasDuration, boolean hasThread, boolean hasStackTrace, boolean hasCutoff) {
|
||||
public synchronized static void addImplicitFields(Type type, boolean requestable, boolean hasDuration, boolean hasThread, boolean hasStackTrace, boolean hasCutoff) {
|
||||
if (!implicitFieldTypes) {
|
||||
createAnnotationType(Timespan.class);
|
||||
createAnnotationType(Timestamp.class);
|
||||
@ -423,7 +417,7 @@ public final class TypeLibrary {
|
||||
// from registered event types. Those types that are not reachable can
|
||||
// safely be removed
|
||||
// Returns true if type was removed
|
||||
public boolean clearUnregistered() {
|
||||
public static synchronized boolean clearUnregistered() {
|
||||
Logger.log(LogTag.JFR_METADATA, LogLevel.TRACE, "Cleaning out obsolete metadata");
|
||||
List<Type> registered = new ArrayList<>();
|
||||
for (Type type : types.values()) {
|
||||
@ -452,11 +446,11 @@ public final class TypeLibrary {
|
||||
return !removeIds.isEmpty();
|
||||
}
|
||||
|
||||
public void addType(Type type) {
|
||||
public static synchronized void addType(Type type) {
|
||||
addTypes(Collections.singletonList(type));
|
||||
}
|
||||
|
||||
public static void addTypes(List<Type> ts) {
|
||||
public static synchronized void addTypes(List<Type> ts) {
|
||||
if (!ts.isEmpty()) {
|
||||
visitReachable(ts, t -> !types.containsKey(t.getId()), t -> types.put(t.getId(), t));
|
||||
}
|
||||
@ -504,7 +498,7 @@ public final class TypeLibrary {
|
||||
}
|
||||
}
|
||||
|
||||
public void removeType(long id) {
|
||||
public static synchronized void removeType(long id) {
|
||||
types.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user