Skip to content

Breaking change: fory-core 1.3.0 requires --add-opens=java.base/java.lang.invoke=ALL-UNNAMED on JDK 25 #3788

Description

@juliojgd

Search before asking

  • I had searched in the issues and found no similar issues.

Version

Fory 1.3.0
OpenJDK 25.0.3
Maven 3.9.14

Component(s)

Java

Minimal reproduce step

In our case, Fory is initialized in a standard way, for example:

var foryBuilder = Fory.builder()
    .withLanguage(Language.JAVA)
    .requireClassRegistration(false)
    .withRefTracking(true);

var fory = foryBuilder.buildThreadSafeForyPool(maxPoolSize);

What did you expect to see?

Upgrading from 1.2.0 to 1.3.0 with no code changes should not break the runtime

What did you see instead?

We consistently see failures like:

Caused by: java.lang.IllegalStateException: JDK25+ string internals are inaccessible. JDK25 zero-Unsafe mode requires java.base/java.lang.invoke to be open to Fory. Use --add-opens=java.base/java.lang.invoke=ALL-UNNAMED when Fory is on the classpath, or --add-opens=java.base/java.lang.invoke=org.apache.fory.core when Fory is on the module path.
    at org.apache.fory.serializer.PlatformStringUtils.stringHandles(PlatformStringUtils.java:94)
    at org.apache.fory.serializer.PlatformStringUtils.<clinit>(PlatformStringUtils.java:35)

Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field static final java.lang.invoke.MethodHandles$Lookup java.lang.invoke.MethodHandles$Lookup.IMPL_LOOKUP accessible: module java.base does not "opens java.lang.invoke" to unnamed module

We also see follow-up failures such as:

java.lang.NoClassDefFoundError: Could not initialize class org.apache.fory.serializer.PlatformStringUtils

Anything Else?

Hello,

after upgrading org.apache.fory:fory-core from 1.2.0 to 1.3.0, we started seeing runtime failures on JDK 25 in code paths that initialize Fory.

Summary

fory-core:1.3.0 appears to require this extra JVM flag on JDK 25:

--add-opens=java.base/java.lang.invoke=ALL-UNNAMED

Without that flag, Fory fails during initialization.

This looks like a breaking behavioral change for consumers upgrading from 1.2.0 to 1.3.0, because the dependency bump alone can break previously working applications/tests at runtime.

Error

We consistently see failures like:

Caused by: java.lang.IllegalStateException: JDK25+ string internals are inaccessible. JDK25 zero-Unsafe mode requires java.base/java.lang.invoke to be open to Fory. Use --add-opens=java.base/java.lang.invoke=ALL-UNNAMED when Fory is on the classpath, or --add-opens=java.base/java.lang.invoke=org.apache.fory.core when Fory is on the module path.
    at org.apache.fory.serializer.PlatformStringUtils.stringHandles(PlatformStringUtils.java:94)
    at org.apache.fory.serializer.PlatformStringUtils.<clinit>(PlatformStringUtils.java:35)

Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field static final java.lang.invoke.MethodHandles$Lookup java.lang.invoke.MethodHandles$Lookup.IMPL_LOOKUP accessible: module java.base does not "opens java.lang.invoke" to unnamed module

We also see follow-up failures such as:

java.lang.NoClassDefFoundError: Could not initialize class org.apache.fory.serializer.PlatformStringUtils

Environment

  • Fory: 1.3.0
  • JDK: 25
  • Classpath usage, not module path
  • The same code path worked before the upgrade to 1.3.0

Usage pattern

In our case, Fory is initialized in a standard way, for example:

var foryBuilder = Fory.builder()
    .withLanguage(Language.JAVA)
    .requireClassRegistration(false)
    .withRefTracking(true);

var fory = foryBuilder.buildThreadSafeForyPool(maxPoolSize);

Observed impact

A dependency-only upgrade from 1.2.0 to 1.3.0 caused integration tests and runtime initialization to fail until we added:

--add-opens=java.base/java.lang.invoke=ALL-UNNAMED

Questions

  1. Is this new requirement on JDK 25 expected in 1.3.0?
  2. Was this considered a breaking change?
  3. Can this be avoided? Via a Fory fix or via any code replacement.
  4. Is there a way for Fory to degrade gracefully or fall back instead of failing hard during PlatformStringUtils static initialization?

If useful, we can provide a smaller reproducer, but the behavior is already reproducible in our environment just by upgrading from 1.2.0 to 1.3.0 on JDK 25.

Thanks.

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions