Skip to content

[java] LambdaGetterJsonAccessor and LambdaSetterJsonAccessor break GraalVM Native Image builds #4059

Description

@zhfeng

Description

PR #3960 introduced LambdaGetterJsonAccessor.create(getter) and LambdaSetterJsonAccessor.create(setter) which use LambdaMetafactory to create lambda classes at runtime. This works fine for JVM execution, but fails in GraalVM Native Image builds because Native Image compilation does not allow classes to be defined at runtime by default.

Error

```
com.oracle.svm.core.jdk.UnsupportedFeatureError: Classes cannot be defined at runtime by default when using ahead-of-time Native Image compilation. Tried to define class io/quarkiverse/fory/it/Bar93972LambdawYqQGiABlx4ie47aSPUZJB
at java.base@25.0.4.1/java.lang.invoke.InnerClassLambdaMetafactory.generateInnerClass(InnerClassLambdaMetafactory.java:358)
at java.base@25.0.4.1/java.lang.invoke.InnerClassLambdaMetafactory.spinInnerClass(InnerClassLambdaMetafactory.java:282)
at java.base@25.0.4.1/java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(InnerClassLambdaMetafactory.java:214)
at java.base@25.0.4.1/java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:354)
at org.apache.fory.platform.internal._JDKAccess.makeGetterFunction(_JDKAccess.java:307)
at org.apache.fory.json.meta.JsonFieldAccessor$LambdaGetterJsonAccessor.create(JsonFieldAccessor.java:544)
...
```

Affected Component

java/fory-json/src/main/java/org/apache/fory/json/meta/JsonFieldAccessor.java

The issue affects both:

  • newGetterAccessor() method (line ~202)
  • newSetterAccessor() method (line ~209)

Reproduction

This failure is reproduced in quarkus-fory integration tests:

Suggested Fix

Add GraalvmSupport.isGraalBuildTime() check to both newGetterAccessor() and newSetterAccessor() to ensure lambda classes are only created during GraalVM build time (via the Native Image Feature), not at runtime:

```java
private static JsonFieldAccessor newGetterAccessor(Member member) {
Method getter = (Method) member;
return GraalvmSupport.isGraalBuildTime() && USE_JDK25_NATIVE_ACCESS
? LambdaGetterJsonAccessor.create(getter)
: new GetterJsonAccessor(getter);
}

private static JsonFieldAccessor newSetterAccessor(Member member) {
Method setter = (Method) member;
return GraalvmSupport.isGraalBuildTime() && USE_JDK25_NATIVE_ACCESS && setter.getParameterCount() == 1
? LambdaSetterJsonAccessor.create(setter)
: new SetterJsonAccessor(setter);
}
```

See discussion in PR #3960: #3960 (comment)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions