Skip to content

Provide Java 21 forward compatibility. - #779

Merged
blackwinter merged 4 commits into
masterfrom
765-provideJava21ForwardCompatibility
Jul 14, 2026
Merged

Provide Java 21 forward compatibility.#779
blackwinter merged 4 commits into
masterfrom
765-provideJava21ForwardCompatibility

Conversation

@blackwinter

Copy link
Copy Markdown
Member

Serves in preparation for raising the minimum Java version to 21 (#765).

  • Upgrade EqualsVerifier dependency to version 3.19.4 (latest pre-4 release) and add prefab values for type java.util.regex.Matcher.
  • Include Nashorn Javascript engine as standalone library (removed as built-in in JDK 15; see JEP 372 and documentation).
  • Replace deprecated Locale constructor (deprecated in JDK 19).
  • Replace deprecated URL constructor (deprecated in JDK 20).

Providing Java 21 forward compatibility (#765; see below).

--------

* JDK 21:

HashValueTest > shouldSatisfyEqualsContract() FAILED
    java.lang.AssertionError: EqualsVerifier found a problem in class org.metafacture.metafix.Value$Hash.
    -> Java 21 (65) is not supported by the current version of Byte Buddy which officially supports Java 18 (62) - update Byte Buddy or set net.bytebuddy.experimental as a VM property

    For more information, go to: https://www.jqno.nl/equalsverifier/errormessages
        at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:315)
        at org.metafacture.metafix.HashValueTest.shouldSatisfyEqualsContract(HashValueTest.java:49)

        Caused by:
        java.lang.IllegalArgumentException: Java 21 (65) is not supported by the current version of Byte Buddy which officially supports Java 18 (62) - update Byte Buddy or set net.bytebuddy.experimental as a VM property
            at nl.jqno.equalsverifier.internal.lib.bytebuddy.utility.OpenedClassReader.of(OpenedClassReader.java:96)
            at nl.jqno.equalsverifier.internal.lib.bytebuddy.pool.TypePool$Default.parse(TypePool.java:855)
            at nl.jqno.equalsverifier.internal.lib.bytebuddy.pool.TypePool$Default.doDescribe(TypePool.java:841)
            at nl.jqno.equalsverifier.internal.lib.bytebuddy.pool.TypePool$AbstractBase.describe(TypePool.java:574)
            at nl.jqno.equalsverifier.internal.lib.bytebuddy.pool.TypePool$AbstractBase$Hierarchical.describe(TypePool.java:657)
            at nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCacheBuilder.build(AnnotationCacheBuilder.java:39)
            at nl.jqno.equalsverifier.internal.util.Configuration.buildAnnotationCache(Configuration.java:130)
            at nl.jqno.equalsverifier.internal.util.Configuration.build(Configuration.java:90)
            at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.buildConfig(SingleTypeEqualsVerifierApi.java:380)
            at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.performVerification(SingleTypeEqualsVerifierApi.java:366)
            at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:311)
            ... 1 more

* EqualsVerifier 3.15:

HashValueTest > shouldSatisfyEqualsContract() FAILED
    java.lang.AssertionError: EqualsVerifier found a problem in class org.metafacture.metafix.Value$Hash.
    -> Unable to make field private int[] java.util.regex.IntHashSet.entries accessible: module java.base does not "opens java.util.regex" to unnamed module @74287ea3

    For more information, go to: https://www.jqno.nl/equalsverifier/errormessages
    (EqualsVerifier 3.15, JDK 21.0.11 on Linux)
        at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:351)
        at org.metafacture.metafix.HashValueTest.shouldSatisfyEqualsContract(HashValueTest.java:49)

        Caused by:
        java.lang.reflect.InaccessibleObjectException: Unable to make field private int[] java.util.regex.IntHashSet.entries accessible: module java.base does not "opens java.util.regex" to unnamed module @74287ea3
            at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391)
            at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367)
            at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315)
            at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:183)
            at java.base/java.lang.reflect.Field.setAccessible(Field.java:177)
            at nl.jqno.equalsverifier.internal.reflection.FieldModifier.change(FieldModifier.java:112)
            at nl.jqno.equalsverifier.internal.reflection.FieldModifier.changeField(FieldModifier.java:100)
            at nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.scramble(InPlaceObjectAccessor.java:52)
            at nl.jqno.equalsverifier.internal.reflection.ClassAccessor.getRedAccessor(ClassAccessor.java:188)
            at nl.jqno.equalsverifier.internal.reflection.ClassAccessor.getRedObject(ClassAccessor.java:177)
            at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.giveInstances(FallbackFactory.java:95)
            at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.createValues(FallbackFactory.java:40)
            at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.createTuple(PrefabValues.java:157)
            at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.realizeCacheFor(PrefabValues.java:140)
            at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.giveArrayInstances(FallbackFactory.java:66)
            at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.createValues(FallbackFactory.java:36)
            at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.createTuple(PrefabValues.java:157)
            at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.realizeCacheFor(PrefabValues.java:140)
            at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.traverseFields(FallbackFactory.java:88)
            at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.createValues(FallbackFactory.java:39)
            at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.createTuple(PrefabValues.java:157)
            at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.realizeCacheFor(PrefabValues.java:140)
            at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.giveTuple(PrefabValues.java:81)
            at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.giveOther(PrefabValues.java:104)
            at nl.jqno.equalsverifier.internal.reflection.FieldModifier.lambda$changeField$2(FieldModifier.java:97)
            at nl.jqno.equalsverifier.internal.reflection.FieldModifier.wrappedChange(FieldModifier.java:118)
            at nl.jqno.equalsverifier.internal.reflection.FieldModifier.lambda$change$3(FieldModifier.java:113)
            at nl.jqno.equalsverifier.internal.util.Rethrow.lambda$rethrow$1(Rethrow.java:51)
            at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:34)
            at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:49)
            at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:59)
            at nl.jqno.equalsverifier.internal.reflection.FieldModifier.change(FieldModifier.java:113)
            at nl.jqno.equalsverifier.internal.reflection.FieldModifier.changeField(FieldModifier.java:100)
            at nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.scramble(InPlaceObjectAccessor.java:52)
            at nl.jqno.equalsverifier.internal.reflection.ClassAccessor.getRedAccessor(ClassAccessor.java:188)
            at nl.jqno.equalsverifier.internal.reflection.ClassAccessor.getRedObject(ClassAccessor.java:177)
            at nl.jqno.equalsverifier.internal.util.Configuration.ensureUnequalExamples(Configuration.java:219)
            at nl.jqno.equalsverifier.internal.util.Configuration.build(Configuration.java:114)
            at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.buildConfig(SingleTypeEqualsVerifierApi.java:424)
            at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.performVerification(SingleTypeEqualsVerifierApi.java:410)
            at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:347)
            ... 1 more

* EqualsVerifier 3.16:

HashValueTest > shouldSatisfyEqualsContract() FAILED
    java.lang.AssertionError: EqualsVerifier found a problem in class org.metafacture.metafix.Value$Hash.
    -> Field patternMatcher of type java.util.regex.Matcher is not accessible via the Java Module System.
    Consider opening the module that contains it, or add prefab values for type java.util.regex.Matcher.

    For more information, go to: https://www.jqno.nl/equalsverifier/errormessages
    (EqualsVerifier 3.16, JDK 21.0.11 on Linux)
        at nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:349)
        at org.metafacture.metafix.HashValueTest.shouldSatisfyEqualsContract(HashValueTest.java:49)

        Caused by:
        nl.jqno.equalsverifier.internal.exceptions.ModuleException
            at app//nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.handleInaccessibleObjectException(InPlaceObjectAccessor.java:108)
            at app//nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.scrambleInternal(InPlaceObjectAccessor.java:82)
            at app//nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.scramble(InPlaceObjectAccessor.java:58)
            at app//nl.jqno.equalsverifier.internal.reflection.ClassAccessor.getRedAccessor(ClassAccessor.java:225)
            at app//nl.jqno.equalsverifier.internal.reflection.ClassAccessor.getRedAccessor(ClassAccessor.java:210)
            at app//nl.jqno.equalsverifier.internal.reflection.ClassAccessor.getRedObject(ClassAccessor.java:186)
            at app//nl.jqno.equalsverifier.internal.util.Configuration.ensureUnequalExamples(Configuration.java:219)
            at app//nl.jqno.equalsverifier.internal.util.Configuration.build(Configuration.java:114)
            at app//nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.buildConfig(SingleTypeEqualsVerifierApi.java:424)
            at app//nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.performVerification(SingleTypeEqualsVerifierApi.java:410)
            at app//nl.jqno.equalsverifier.api.SingleTypeEqualsVerifierApi.verify(SingleTypeEqualsVerifierApi.java:347)
            ... 1 more

            Caused by:
            java.lang.reflect.InaccessibleObjectException: Unable to make field private int[] java.util.regex.IntHashSet.entries accessible: module java.base does not "opens java.util.regex" to unnamed module @74287ea3
                at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391)
                at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367)
                at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315)
                at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:183)
                at java.base/java.lang.reflect.Field.setAccessible(Field.java:177)
                at nl.jqno.equalsverifier.internal.reflection.FieldModifier.change(FieldModifier.java:134)
                at nl.jqno.equalsverifier.internal.reflection.FieldModifier.changeField(FieldModifier.java:122)
                at nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.scrambleInternal(InPlaceObjectAccessor.java:80)
                at nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.scramble(InPlaceObjectAccessor.java:58)
                at nl.jqno.equalsverifier.internal.reflection.ClassAccessor.getRedAccessor(ClassAccessor.java:225)
                at nl.jqno.equalsverifier.internal.reflection.ClassAccessor.getRedObject(ClassAccessor.java:199)
                at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.giveInstances(FallbackFactory.java:99)
                at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.createValues(FallbackFactory.java:40)
                at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.createTuple(PrefabValues.java:179)
                at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.realizeCacheFor(PrefabValues.java:162)
                at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.giveArrayInstances(FallbackFactory.java:66)
                at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.createValues(FallbackFactory.java:36)
                at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.createTuple(PrefabValues.java:179)
                at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.realizeCacheFor(PrefabValues.java:162)
                at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.traverseFields(FallbackFactory.java:88)
                at nl.jqno.equalsverifier.internal.prefabvalues.factories.FallbackFactory.createValues(FallbackFactory.java:39)
                at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.createTuple(PrefabValues.java:179)
                at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.realizeCacheFor(PrefabValues.java:162)
                at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.giveTuple(PrefabValues.java:93)
                at nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues.giveOther(PrefabValues.java:130)
                at nl.jqno.equalsverifier.internal.reflection.FieldModifier.lambda$changeField$2(FieldModifier.java:119)
                at nl.jqno.equalsverifier.internal.reflection.FieldModifier.wrappedChange(FieldModifier.java:140)
                at nl.jqno.equalsverifier.internal.reflection.FieldModifier.lambda$change$3(FieldModifier.java:135)
                at nl.jqno.equalsverifier.internal.util.Rethrow.lambda$rethrow$1(Rethrow.java:51)
                at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:34)
                at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:49)
                at nl.jqno.equalsverifier.internal.util.Rethrow.rethrow(Rethrow.java:59)
                at nl.jqno.equalsverifier.internal.reflection.FieldModifier.change(FieldModifier.java:135)
                at nl.jqno.equalsverifier.internal.reflection.FieldModifier.changeField(FieldModifier.java:122)
                at nl.jqno.equalsverifier.internal.reflection.InPlaceObjectAccessor.scrambleInternal(InPlaceObjectAccessor.java:80)
                ... 10 more

HashValueTest > shouldSatisfyEqualsContract() STANDARD_ERROR
    WARNING: A Java agent has been loaded dynamically ([...]/byte-buddy-agent-1.12.19.jar)
    WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
    WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
    WARNING: Dynamic loading of agents will be disallowed by default in a future release
Providing Java 21 forward compatibility (#765; JDK 15: Remove the Nashorn JavaScript Engine [JEP 372]).

See also: https://github.com/szegedi/nashorn/wiki/Using-Nashorn-with-different-Java-versions

--------

* JDK 21:

ScriptTest > shouldExecuteJavascriptFunctions FAILED
    org.metafacture.metamorph.MetamorphException: Error while building the Metamorph transformation pipeline: Cannot set file on class Script
        at app//org.metafacture.metamorph.Metamorph.buildPipeline(Metamorph.java:303)
        at app//org.metafacture.metamorph.Metamorph.<init>(Metamorph.java:293)
        at app//org.metafacture.metamorph.Metamorph.<init>(Metamorph.java:269)
        at app//org.metafacture.metamorph.Metamorph.<init>(Metamorph.java:258)
        at app//org.metafacture.metamorph.InlineMorph.create(InlineMorph.java:147)
        at app//org.metafacture.metamorph.InlineMorph.createConnectedTo(InlineMorph.java:187)
        at app//org.metafacture.metamorph.TestHelpers.assertMorph(TestHelpers.java:45)
        at app//org.metafacture.metamorph.TestHelpers.assertMorph(TestHelpers.java:41)
        at app//org.metafacture.metamorph.functions.ScriptTest.shouldExecuteJavascriptFunctions(ScriptTest.java:47)

        Caused by:
        org.metafacture.commons.reflection.ReflectionException: Cannot set file on class Script
            at app//org.metafacture.commons.reflection.ConfigurableClass.applySetters(ConfigurableClass.java:195)
            at app//org.metafacture.commons.reflection.ConfigurableClass.newInstance(ConfigurableClass.java:145)
            at app//org.metafacture.commons.reflection.ObjectFactory.newInstance(ObjectFactory.java:105)
            at app//org.metafacture.metamorph.MorphBuilder.handleFunction(MorphBuilder.java:325)
            at app//org.metafacture.metamorph.AbstractMetamorphDomWalker.handlePostprocess(AbstractMetamorphDomWalker.java:289)
            at app//org.metafacture.metamorph.AbstractMetamorphDomWalker.handleRule(AbstractMetamorphDomWalker.java:268)
            at app//org.metafacture.metamorph.AbstractMetamorphDomWalker.handleRules(AbstractMetamorphDomWalker.java:238)
            at app//org.metafacture.metamorph.AbstractMetamorphDomWalker.walk(AbstractMetamorphDomWalker.java:152)
            at app//org.metafacture.metamorph.AbstractMetamorphDomWalker.walk(AbstractMetamorphDomWalker.java:126)
            at app//org.metafacture.metamorph.AbstractMetamorphDomWalker.walk(AbstractMetamorphDomWalker.java:117)
            at app//org.metafacture.metamorph.Metamorph.buildPipeline(Metamorph.java:300)
            ... 8 more

            Caused by:
            java.lang.reflect.InvocationTargetException
                at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:115)
                at java.base/java.lang.reflect.Method.invoke(Method.java:580)
                at org.metafacture.commons.reflection.ConfigurableClass.applySetters(ConfigurableClass.java:191)
                ... 18 more

                Caused by:
                java.lang.NullPointerException: Cannot invoke "javax.script.ScriptEngine.eval(java.io.Reader)" because "engine" is null
                    at org.metafacture.metamorph.functions.Script.setFile(Script.java:66)
                    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
                    ... 20 more
Providing Java 21 forward compatibility (#765; JDK 19: "Locale constructors have been deprecated. See Obtaining a Locale for other options.").

--------

* JDK 21: "warning: [deprecation] Locale(String) in Locale has been deprecated"
…uctor).

Providing Java 21 forward compatibility (#765; JDK 20: "The `java.net.URL` constructors are deprecated. Developers are encouraged to use `java.net.URI` to parse or construct a URL.").

--------

* JDK 21:

- "warning: [deprecation] URL(String) in URL has been deprecated"
- "warning: [deprecation] URL(URL,String) in URL has been deprecated"
@blackwinter
blackwinter requested review from dr0i and fsteeg July 8, 2026 15:34
@blackwinter blackwinter moved this to Review in Metafacture Jul 8, 2026
@dr0i
dr0i removed their request for review July 13, 2026 09:34
@fsteeg fsteeg assigned blackwinter and unassigned fsteeg Jul 14, 2026
@blackwinter
blackwinter merged commit 820b06f into master Jul 14, 2026
2 checks passed
@github-project-automation github-project-automation Bot moved this from Review to Done in Metafacture Jul 14, 2026
@blackwinter
blackwinter deleted the 765-provideJava21ForwardCompatibility branch July 14, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants