diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java index eb9e1ba1ffe..9429d6e5c94 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java @@ -57,7 +57,6 @@ public final class MetadataRepository { private final List nativeEventTypes = new ArrayList<>(150); private final List nativeControls = new ArrayList(nativeEventTypes.size()); - private final TypeLibrary typeLibrary = TypeLibrary.getInstance(); private final SettingsManager settingsManager = new SettingsManager(); private final Map> mirrors = new HashMap<>(); private Constructor 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 types = typeLibrary.getVisibleTypes(); + List 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 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 getVisibleTypes() { - return typeLibrary.getVisibleTypes(); + return TypeLibrary.getVisibleTypes(); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java index c6f088f1e9a..dd18e31e531 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java @@ -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 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 jvmTypes) { - visitReachable(jvmTypes, t -> !types.containsKey(t.getId()), t -> types.put(t.getId(), t)); - if (Logger.shouldLog(LogTag.JFR_SYSTEM_METADATA, LogLevel.INFO)) { - Stream 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 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 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 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 getTypes() { - return types.values(); + public static synchronized Collection getTypes() { + return new ArrayList<>(types.values()); } // Returned list should be mutable (for in-place sorting) - public List getVisibleTypes() { + public static synchronized List getVisibleTypes() { List 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 a) { + public static synchronized Type createAnnotationType(Class 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 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 dynamicAnnotations, List dynamicFields) { + public static synchronized Type createType(Class clazz, List dynamicAnnotations, List 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 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 ts) { + public static synchronized void addTypes(List 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); } }