RFR: 8307298: JFR: Ensure jdk.jfr.internal.TypeLibrary is initialized only once [v2]
Severin Gehwolf
sgehwolf at openjdk.org
Wed May 10 08:53:32 UTC 2023
On Tue, 9 May 2023 20:31:49 GMT, Robert Toyonaga <duke at openjdk.org> wrote:
>> Hello, may I have a review of a small change that enforces that `jdk.jfr.internal.TypeLibrary` only gets initialized once?
>> Previously, it was the case that `TypeLibrary` was only initialized once, but since [this change](https://github.com/openjdk/jdk/pull/12884/files) it can now be initialized multiple times. This can be a problem because re-initialization [results in attempting to add elements to `jdk.jfr.internal.Type#fields`](https://github.com/openjdk/jdk/blob/master/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataLoader.java#L264) which may have already been changed to an unmodifiableList after the initial initialization of `TypeLibrary`.
>>
>> This is of concern for JFR support in GraalVM Native Image. Specifically, multiple initializations of TypeLibrary breaks the ability to use JFR at native image built time. This is because, if JFR is used at image build time, the data of a few of the JFR singletons such as MetadataRepository must be re-initialized for runtime recordings to start with a "clean-slate". However, re-initializing MetadataRepository, also has the effect of calling `TypeLibrary#initialize()` which now unconditionally attempts to initialize TypeRepository, resulting in errors.
>>
>> Example of exception upon second initialization of `TypeRepository`:
>>
>> Caused by: java.lang.InternalError: java.lang.UnsupportedOperationException
>> at jdk.jfr/jdk.jfr.internal.MetadataLoader.createTypes(MetadataLoader.java:195)
>> at jdk.jfr/jdk.jfr.internal.TypeLibrary.initialize(TypeLibrary.java:103)
>> at jdk.jfr/jdk.jfr.internal.MetadataRepository.initializeJVMEventTypes(MetadataRepository.java:72)
>> at jdk.jfr/jdk.jfr.internal.MetadataRepository.<init>(MetadataRepository.java:68)
>> at org.graalvm.nativeimage.builder/com.oracle.svm.core.jfr.Target_jdk_jfr_internal_MetadataRepository.<clinit>(Target_jdk_jfr_internal_MetadataRepository.java:42)
>> at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
>> at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1160)
>> at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.classinitialization.ClassInitializationSupport.ensureClassInitialized(ClassInitializationSupport.java:168)
>> ... 11 more
>> Caused by: java.lang.UnsupportedOperationException
>> at java.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1085)
>> at jdk.jfr/jdk.jfr.internal.Type.add(Type.java:227)
>> at jdk.jfr/jdk.jfr.internal.MetadataLoader.addFields(MetadataLoader.java:264)
>> at jdk.jfr/jdk.jfr.internal.MetadataLoader.buildTypes(MetadataLoader.java:202)
>> at jdk.jfr/jdk.jfr.internal.MetadataLoader.createTypes(MetadataLoader.java:193)
>
> Robert Toyonaga has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains two additional commits since the last revision:
>
> - Merge branch 'master' of github.com:openjdk/jdk into initialize-TypeLibrary-once
> - Only init TypeLibrary once
src/jdk.jfr/share/classes/jdk/jfr/internal/TypeLibrary.java line 103:
> 101: if (initialized) {
> 102: return;
> 103: }
Perhaps it would make sense to add a comment as to why that check needs to be there? Something like this perhaps?
// TypeLibrary is initialized once by MetadataRepository (which is a singleton). So shouldn't happen practice.
// However, some tools (GraalVM native image) may call the initialization routine twice.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/13760#discussion_r1189561489
More information about the hotspot-jfr-dev
mailing list