quarkus: Java 17 records don't work in native image with GraalVM 21.3.0 JDK 17

Describe the bug

Java 17 records don’t work with GraalVM 21.3.0 when used as return types of resources that produce application/json. They also fail with SmallRye GraphQL.

In the reproducer I used quarkus-resteasy-jackson because Jackson supports records out of the box without any configuration.

When I create a native image like that with GraalVM 21.3 it works as expected.

public class App {

	public static void main(String[] args) {

		System.out.println(new F("x"));
	}

	static record F(String x) {
	}
}

Expected behavior

Quarkus native should produce a binary.

Actual behavior

Native compilation fails with:

Error: com.oracle.svm.hosted.substitute.DeletedElementException: Unsupported method java.lang.Class.getConstantPool() is reachable: The declaring class of this element has been substituted, but this element is not present in the substitution class
To diagnose the issue, you can add the option --report-unsupported-elements-at-runtime. The unsupported element is then reported at run time when it is accessed the first time.
Detailed message:
Trace: 
	at parsing java.lang.System$2.getConstantPool(System.java:2262)
Call path from entry point to java.lang.System$2.getConstantPool(Class): 
	at java.lang.System$2.getConstantPool(System.java:2262)
	at java.lang.reflect.RecordComponent.declaredAnnotations(RecordComponent.java:198)
	at java.lang.reflect.RecordComponent.getAnnotation(RecordComponent.java:181)
	at io.smallrye.config.ConfigMappingInterface.getPropertyName(ConfigMappingInterface.java:691)
	at io.smallrye.config.ConfigMappingInterface.getPropertyDef(ConfigMappingInterface.java:622)
	at io.smallrye.config.ConfigMappingInterface.getProperties(ConfigMappingInterface.java:607)
	at io.smallrye.config.ConfigMappingInterface.createConfigurationInterface(ConfigMappingInterface.java:564)
	at io.smallrye.config.ConfigMappingInterface.access$000(ConfigMappingInterface.java:27)
	at io.smallrye.config.ConfigMappingInterface$1.computeValue(ConfigMappingInterface.java:32)
	at io.smallrye.config.ConfigMappingInterface$1.computeValue(ConfigMappingInterface.java:30)
	at com.oracle.svm.core.jdk.Target_java_lang_ClassValue.get(JavaLangSubstitutions.java:596)
	at io.quarkus.runtime.configuration.Substitutions$Target_ConfigMappingInterface.getConfigurationInterface(Substitutions.java:86)
	at io.smallrye.config.ConfigMappingContext.lambda$getKeyConverter$6(ConfigMappingContext.java:142)
	at io.smallrye.config.ConfigMappingContext$$Lambda$1290/0x00000007c1585240.apply(Unknown Source)
	at sun.security.ec.ParametersMap$1.get(ParametersMap.java:78)
	at com.oracle.svm.core.jdk.SystemPropertiesSupport.initializeLazyValue(SystemPropertiesSupport.java:216)
	at com.oracle.svm.core.jdk.SystemPropertiesSupport.getProperty(SystemPropertiesSupport.java:169)
	at com.oracle.svm.core.jdk.Target_java_lang_System.getProperty(JavaLangSubstitutions.java:287)
	at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_ARRAY_System_getProperty_deeeaa72a006d330408a3b7d002c7533e108bc28(generated:0)

How to Reproduce?

Given the following dependency:

<dependency>
	<groupId>io.quarkus</groupId>
	<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>

This record:

public record Thing(String name) {
}

and the following resource

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class ExampleResource {

	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Thing hello() {
		return new Thing("Hello RESTEasy");
	}
}

A request like curl localhost:8080/hello returns

{"name":"Hello RESTEasy"}

The whole project is here: restrecords.zip

Reproduce with

 ./mvnw clean package -Pnative

on GraalVM 21.3 Java 17

An example using SmallRye GraphQL is available here: https://github.com/michael-simons/neo4j-aura-quarkus-graphql/tree/jdk17

Output of uname -a or ver

Darwin bs62.XXX 20.6.0 Darwin Kernel Version 20.6.0: Mon Aug 30 06:12:21 PDT 2021; root:xnu-7195.141.6~3/RELEASE_X86_64 x86_64

Output of java -version

openjdk version “17.0.1” 2021-10-19 OpenJDK Runtime Environment GraalVM CE 21.3.0 (build 17.0.1+12-jvmci-21.3-b05) OpenJDK 64-Bit Server VM GraalVM CE 21.3.0 (build 17.0.1+12-jvmci-21.3-b05, mixed mode, sharing)

GraalVM version (if different from Java)

21.3.0

Quarkus version or git rev

2.3.0

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)

Additional information

No response

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 2
  • Comments: 19 (15 by maintainers)

Most upvoted comments

Upstream Graal VM will have this fixed in 21.3.2 and 22.1 releases (April 2022). Mandrel included this fix in 21.3.1.1-Final early, but will sync with upstream in April.

Closing this as Quarkus 2.10 will use GraalVM 22.1.

Same issue here. Working adding --report-unsupported-elements-at-runtime but shouldn’t be the best option IMO…

@zakkak this is still an issue with the released version of 21.3. Do you know anything about this?

I’ll have a look.

I added --report-unsupported-elements-at-runtime to quarkus.native.additional-build-args on the pom.xml and It worked. At github of graalvm have an issue where it’s recommended: https://github.com/oracle/graal/issues/3125.