quarkus: Native image build failures on latest GraalVM with Random/SplittableRandom initialized at build time

Describe the bug Quarkus TS fail with latest Graal (see https://github.com/oracle/graal/actions/runs/546718036)

In the upcoming release of GraalVM (21.1) instances of Random/SplittableRandom class won’t be allowed in the native image heap. The corresponding patch can be seen here.

As a result, moving forward Quarkus needs to ensure that its core and extensions reinitialize any classes holding instances of Random/SplittableRandom class.

In order to find out which classes to reinitialize one needs to run:

./mvnw verify \
  -Dnative \
  -Dquarkus.native.additional-build-args="--trace-object-instantiation=java.security.SecureRandom" \
  -pl integration-tests/main

This will print out something like this:

Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Detected an instance of Random/SplittableRandom class in the image heap. Instances created during image generation have cached seed values and don't behave as expected.  Object has been initialized by the org.apache.http.impl.auth.NTLMEngineImpl class initializer with a trace: 
        at java.security.SecureRandom.<init>(SecureRandom.java:323)
        at java.security.SecureRandom.getInstance(SecureRandom.java:383)
        at org.apache.http.impl.auth.NTLMEngineImpl.<clinit>(NTLMEngineImpl.java:103)
. Try avoiding to initialize the class that caused initialization of the object. The object was probably created by a class initializer and is reachable from a static field. You can request class initialization at image runtime by using the option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.
Detailed message:
Trace: 
        at parsing org.apache.http.impl.auth.NTLMEngineImpl.access$000(NTLMEngineImpl.java:51)
Call path from entry point to org.apache.http.impl.auth.NTLMEngineImpl.access$000(): 
        at org.apache.http.impl.auth.NTLMEngineImpl.access$000(NTLMEngineImpl.java:51)
        at org.apache.http.impl.auth.NTLMEngineImpl$Type3Message.<init>(NTLMEngineImpl.java:1505)
        at org.apache.http.impl.auth.NTLMEngineImpl$Type3Message.<init>(NTLMEngineImpl.java:1474)
        at org.apache.http.impl.auth.NTLMEngineImpl.getType3Message(NTLMEngineImpl.java:181)
        at org.apache.http.impl.auth.NTLMEngineImpl.generateType3Msg(NTLMEngineImpl.java:2097)
        at org.apache.http.impl.auth.NTLMScheme.authenticate(NTLMScheme.java:142)
        at org.apache.http.impl.auth.AuthSchemeBase.authenticate(AuthSchemeBase.java:136)
        at org.apache.http.impl.auth.HttpAuthenticator.doAuth(HttpAuthenticator.java:233)
        at org.apache.http.impl.auth.HttpAuthenticator.generateAuthResponse(HttpAuthenticator.java:213)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:262)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
        at org.jboss.resteasy.client.jaxrs.engines.ManualClosingApacheHttpClient43Engine.invoke(ManualClosingApacheHttpClient43Engine.java:268)
        at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:488)
        at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.lambda$executorSubmit$11(ClientInvocation.java:770)
        at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation$$Lambda$2014/0x00000007c4cd7840.get(Unknown Source)
        at com.oracle.svm.core.jdk.SystemPropertiesSupport.initializeLazyValue(SystemPropertiesSupport.java:211)
        at com.oracle.svm.core.jdk.SystemPropertiesSupport.getProperty(SystemPropertiesSupport.java:164)
        at com.oracle.svm.core.jdk.Target_java_lang_System.getProperty(JavaLangSubstitutions.java:293)
        at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VA_LIST:Ljava_lang_System_2_0002egetProperty_00028Ljava_lang_String_2_00029Ljava_lang_String_2(generated:0)

Which indicates that Quarkus should reinitialize NTLMEngineImpl at runtime.

Expected behavior Tests should pass (at least most of them)

Actual behavior Multiple integration tests fail.

  • Main
  • Hibernate Tenancy
  • Flyway
  • Redis Client
  • Hibernate Search ORM + Elasticsearch
  • Elasticsearch REST client
  • Elasticsearch REST high level client
  • Bouncy Castle
  • Bouncy Castle FIPS
  • Bouncy Castle JSSE
  • Elytron Security LDAP
  • more… fail with:
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Detected an instance of Random/SplittableRandom class in the image heap. Instances created during image generation have cached seed values and don't behave as expected.  To see how this object got instantiated use --trace-object-instantiation=java.security.SecureRandom. The object was probably created by a class initializer and is reachable from a static field. You can request class initialization at image runtime by using the option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.

To Reproduce

  1. Build GraalVM master with: mx --primary-suite-path substratevm --components='Native Image' build
  2. export GRAALVM_HOME=/path/to/graal/sdk/latest_graalvm_home
  3. ./mvnw clean verify -Dnative -Dnative.surefire.skip -pl integration-tests/main

Environment (please complete the following information):

  • Output of uname -a or ver: Linux 5.10.10-200.fc33.x86_64
  • Output of java -version: 11.0.9+10-jvmci-21.0-b03
  • GraalVM version (if different from Java): Graal master ca436f5a8d260027da4218761ee1b83a4d0b4a0f
  • Quarkus version or git rev: Quarkus master dac8d8b4df5f09060057cacba96ce65826b147d0
  • Build tool (ie. output of mvnw --version or gradlew --version): Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 49 (40 by maintainers)

Commits related to this issue

Most upvoted comments

@EdwinKorsten @akuzni2 I was able to fix this by adding

--initialize-at-run-time=org.apache.http.impl.auth.NTLMEngineImpl

in additional build arg. Also I had to use aws sdk v2 instead of v1

I’m getting this error when converting one of my applications to Quarkus to build a native-image using GraalVM 21.1.0. From this thread I can’t really tell what I need to do to get around it.

I’m building my quarkus project with Quarkus 1.13.4.Final

HI @zakkak @dufoli thanks for commenting back. I’ve upgraded to Quarkus 2.0.0 and I still see the same issue cause by some AWS dependencies.

Error: Detected an instance of Random/SplittableRandom class in the image heap. Instances created during image generation have cached seed values and don't behave as expected.  To see how this object got instantiated use --trace-object-instantiation=java.util.Random. The object was probably created by a class initializer and is reachable from a static field. You can request class initialization at image runtime by using the option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.
Trace: Object was reached by 
        reading field com.amazonaws.retry.PredefinedBackoffStrategies$EqualJitterBackoffStrategy.random of
                constant com.amazonaws.retry.PredefinedBackoffStrategies$EqualJitterBackoffStrategy@546fe072 reached by 
        reading field com.amazonaws.retry.PredefinedBackoffStrategies$SDKDefaultBackoffStrategy.equalJitterBackoffStrategy of
                constant com.amazonaws.retry.PredefinedBackoffStrategies$SDKDefaultBackoffStrategy@4d11ec9e reached by 
        reading field com.amazonaws.retry.RetryPolicy.backoffStrategy of
                constant com.amazonaws.retry.RetryPolicy@28b37dae reached by 
        scanning method com.amazonaws.ClientConfiguration.<init>(ClientConfiguration.java:155)
Call path from entry point to com.amazonaws.ClientConfiguration.<init>(ClientConfiguration): 
        at com.amazonaws.ClientConfiguration.<init>(ClientConfiguration.java:378)
        at com.amazonaws.client.builder.AwsClientBuilder.resolveClientConfiguration(AwsClientBuilder.java:169)
        at com.amazonaws.client.builder.AwsClientBuilder.access$000(AwsClientBuilder.java:54)
        at com.amazonaws.client.builder.AwsClientBuilder$SyncBuilderParams.<init>(AwsClientBuilder.java:505)
        at com.amazonaws.client.builder.AwsClientBuilder.getSyncClientParams(AwsClientBuilder.java:441)
        at com.amazonaws.client.builder.AwsSyncClientBuilder.build(AwsSyncClientBuilder.java:46)
        at com.mycompany.service.ApiServiceImpl.<init>(ApiServiceImpl.java:23)
        at com.mycompany.service.ProcessingService.<init>(ProcessingService.java:22)
        at com.mycompany.service.ProcessingService_Bean.create(ProcessingService_Bean.zig:140)
        at com.mycompany.service.ProcessingService_Bean.create(ProcessingService_Bean.zig:155)
        at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
        at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
        at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
        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:291)
        at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VA_LIST:Ljava_lang_System_2_0002egetProperty_00028Ljava_lang_String_2_00029Ljava_lang_String_2(generated:0)

I’m not really sure how to perform the recommendation by the error message

Or you can write your own initialization methods and call them explicitly from your main entry point.

If you have any ideas please let me know.

@zakkak @jerboaa I just wanted to thank you both for this work!

I’ve been getting the same Random/SplittableRandom error. I’m currently following the Quarkus Lambda guide (https://quarkus.io/guides/amazon-lambda) using the Quarkus 2.7.3.Final with GraalVM 21.3.1. I’m using the DynamoDB client from Java SDK v2.

Update: managed to get it to work by following the sample code found here: https://github.com/quarkusio/quarkus-quickstarts/blob/main/amazon-dynamodb-quickstart/pom.xml. Specifically by the use of the quarkus-amazon-dynamodb dependency instead of including the AWS SDK directly. I don’t see this mentioned in any of the guides. Working now and man is the Lambda function fast! Great work.

@jerboaa No, i didn’t. I pulled up the versions and didn`t know i had to add this, thats a nice hint, thanks and sorry for pulling this issue up again.

Maybe a build error from the quarkus plugin would be nice, if the apache client dependency was added and the quarkus-apache-client extension was missing. Just as a hint for ppl upgrading or not reading the documentation properly 😃

Hi @dufoli, my understanding is that https://github.com/quarkiverse/quarkus-cxf/commit/8804ddad2bee27311d63f33d2ec6d2befde2dc8f fixed the above issue, is that right?

Thank you @jerboaa!

Job for latest Quarkus vs latest Graal now that #15962 is fixed: https://github.com/zakkak/graalvm-quarkus-ci/actions/runs/683707199

Now that looks a lot better already! Thank you.