apache / apache/ignite

JDK 22+ regression: IgniteUtils.forceEmptyConstructor(List.class) fails with UnsupportedOperationException (JDK‑8315811)

Open
#12,648 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
5.1k
Forks
1.9k
Avg merge
3d 2h
Merged PRs (30d)
46

Description

### Affected versions

Ignite: I tested with 2.17.0
JDK: 22+

### Steps to reproduce
Run the following minimal program on JDK 22 with Ignite on the classpath and with `--add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED`:
```
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.util.IgniteUtils;
import java.lang.reflect.Constructor;
import java.util.List;

public class Main {
public static void main(String[] args) throws IgniteCheckedException {
Constructor c = IgniteUtils.forceEmptyConstructor(List.class);
System.out.println(c);
}
}
```
With JDK 21, the following would get printed: `public java.lang.Object()`
With JDK 22+, this exception is raised:
```
Exception in thread "main" class org.apache.ignite.IgniteCheckedException: Failed to get object constructor for class: interface java.util.List
at org.apache.ignite.internal.util.IgniteUtils.forceEmptyConstructor(IgniteUtils.java:1691)
at org.example.Main.main(Main.java:15)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.apache.ignite.internal.util.IgniteUtils.forceEmptyConstructor(IgniteUtils.java:1688)
... 1 more
Caused by: java.lang.UnsupportedOperationException: public java.lang.Object() not a superclass of java.util.List
at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.newSerializableConstructorAccessor(MethodHandleAccessorFactory.java:122)
at java.base/jdk.internal.reflect.ReflectionFactory.generateConstructor(ReflectionFactory.java:389)
at java.base/jdk.internal.reflect.ReflectionFactory.newConstructorForSerialization(ReflectionFactory.java:288)
at jdk.unsupported/sun.reflect.ReflectionFactory.newConstructorForSerialization(ReflectionFactory.java:100)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
... 3 more
```
### Root cause
JDK 22 reimplemented sun.reflect.ReflectionFactory::newConstructorForSerialization using method handles (JDK‑8315810 / CSR JDK‑8315811). As part of that change, the JDK now fails fast and throws UnsupportedOperationException when newConstructorForSerialization(C, ctor) is invoked with a ctor whose declaring class is not a superclass of C. This is precisely what happens when C is an interface such as java.util.List: Object is not considered a superclass of an interface, hence the failure.

- CSR note: The only behavioral change is the error case when `newConstructorForSerialization(C.class, ctor)` is called with a constructor whose declaring class is not a superclass of `C`. The old implementation returns an ill-formed constructor and if `newInstance` is invoked, the behavior is unspecified. The new implementation of ReflectionFactory::newConstructorForSerialization throws `UnsupportedOperationException` instead to fail fast.

Is this something that should be handled on ignite's end? Can we add a check on the class type to see if it's an interface first?

Contributor guide

Open the contributing guide

Research direction

Start with IgniteUtils.forceEmptyConstructor in IgniteUtils.java at the stack-trace locations around lines 1688-1691, then run the provided Main program on JDK 22+ and compare it with JDK 21. Trace how the interface argument reaches ReflectionFactory.newConstructorForSerialization; done means the JDK 22+ regression is handled consistently for java.util.List and the reported failure is covered or verified.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.