Skip to content

[GR-70017][Native Image] MethdHandle for record created at build time can't be invoked at runtime #12220

@chaokunyang

Description

@chaokunyang

Describe the Issue

https://github.com/apache/fory is a serialization framework which supports graalvm. Fory generate MethodHandle for constructor at graal build time. So at runtime, fory can use it to create object instance without configuring reflect-meta.json.

But for record class, when using graalvm 25, the generated method handle can't be invoked. The error message shows that we need to configure the reflect-meta.json. This is unexpected since we've already use method handle created at build time

Using the latest version of GraalVM can resolve many issues.

GraalVM Version

graalvm25

Operating System and Version

Linux

Troubleshooting Confirmation

Run Command

git clone https://github.com/chaokunyang/fory.git
cd fory
git checkout 8fda4723b568caa09adee984729053e8a9026133
cd java
mvn -T10 clean install -DskipTests
cd ../integration_tests/graalvm_tests
mvn -DskipTests=true -Pnative package
./target/main

Expected Behavior

The generated method handle should be able to run without error

Actual Behavior

https://github.com/apache/fory/actions/runs/17966898573/job/51101140914?pr=2652

The 'reachability-metadata.json' file should be located in 'META-INF/native-image/<group-id>/<artifact-id>/' of your project. For further help, see https://www.graalvm.org/latest/reference-manual/native-image/metadata/#reflection
	at org.apache.fory.util.record.RecordUtils.invokeRecordCtrHandle(RecordUtils.java:211)
	at org.apache.fory.graalvm.record.RecordExample2_RecordForyCodec_0.read(RecordExample2_RecordForyCodec_0.java:302)
	at org.apache.fory.Fory.readDataInternal(Fory.java:1054)
	at org.apache.fory.Fory.readRef(Fory.java:939)
	at org.apache.fory.Fory.deserialize(Fory.java:893)
	... 5 more
Caused by: org.graalvm.nativeimage.MissingReflectionRegistrationError: Cannot reflectively invoke constructor 'private org.apache.fory.graalvm.record.RecordExample2$Record(int,java.lang.String,java.util.List,java.util.Map)'. To allow this operation, add the following to the 'reflection' section of 'reachability-metadata.json' and rebuild the native image:
  {
    "type": "org.apache.fory.graalvm.record.RecordExample2$Record",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": [
          "int",
          "java.lang.String",
          "java.util.List",
          "java.util.Map"
        ]
      }
    ]
  }
The 'reachability-metadata.json' file should be located in 'META-INF/native-image/<group-id>/<artifact-id>/' of your project. For further help, see https://www.graalvm.org/latest/reference-manual/native-image/metadata/#reflection
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils.reportInvokedExecutable(MissingReflectionRegistrationUtils.java:110)
	at java.base@25/java.lang.reflect.Constructor.acquireConstructorAccessor(Constructor.java:89)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.methodhandles.Util_java_lang_invoke_MethodHandle.getConstructorAccessor(Target_java_lang_invoke_MethodHandle.java:284)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.methodhandles.Util_java_lang_invoke_MethodHandle.asConstructor(Target_java_lang_invoke_MethodHandle.java:280)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.methodhandles.Util_java_lang_invoke_MethodHandle.invokeInternal(Target_java_lang_invoke_MethodHandle.java:240)
	at java.base@25/java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:102)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.methodhandles.MethodHandleIntrinsicImpl.execute(MethodHandleIntrinsicImpl.java:179)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.methodhandles.Util_java_lang_invoke_MethodHandle.invokeInternal(Target_java_lang_invoke_MethodHandle.java:186)
	at java.base@25/java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:102)
	at java.base@25/java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:96)
	at java.base@25/java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:914)
	at java.base@25/java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:891)
	at java.base@25/java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:109)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.methodhandles.MethodHandleIntrinsicImpl.execute(MethodHandleIntrinsicImpl.java:179)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.methodhandles.Util_java_lang_invoke_MethodHandle.invokeInternal(Target_java_lang_invoke_MethodHandle.java:186)
	at java.base@25/java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:102)
	at java.base@25/java.lang.invoke.LambdaForm$NamedFunction.invokeWithArguments(LambdaForm.java:96)
	at java.base@25/java.lang.invoke.LambdaForm.interpretName(LambdaForm.java:914)
	at java.base@25/java.lang.invoke.LambdaForm.interpretWithArguments(LambdaForm.java:891)
	at java.base@25/java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:109)
	at java.base@25/java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:0)
	at java.base@25/java.lang.invoke.Invokers$Holder.invokeExact_MT(Invokers$Holder)
	at java.base@25/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:735)
	at org.apache.fory.util.record.RecordUtils.invokeRecordCtrHandle(RecordUtils.java:209)
	... 9 more

Steps to Reproduce

git clone https://github.com/chaokunyang/fory.git
cd fory
git checkout 8fda4723b568caa09adee984729053e8a9026133
cd java
mvn -T10 clean install -DskipTests
cd ../integration_tests/graalvm_tests
mvn -DskipTests=true -Pnative package
./target/main

Additional Context

No response

Run-Time Log Output and Error Messages

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions