graal icon indicating copy to clipboard operation
graal copied to clipboard

[GR-59060] [Native Image] Fatal error: com.oracle.svm.core.util.VMError$HostedError: guarantee failed when including java agent (DataDog)

Open matteoluzzi opened this issue 1 year ago • 3 comments

Describe the Issue

HI! I am in the process of migrating an existing spring boot application to Graalvm. One of the requirements is to instrument the application with the Datadog agent, which, according to the documentation (https://docs.datadoghq.com/tracing/trace_collection/compatibility/java/?tab=graalvm#graalvm-native-image-support) is GraalVM compatible. However when compiling the native image by using the native-maven-plugin I get the following error

Fatal error: com.oracle.svm.core.util.VMError$HostedError: guarantee failed
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.shouldNotReachHere(VMError.java:72)

Note that if I used the Liberica Native Image Kit then the compilation succeeds. I have stripped down my project and found out that the error is triggered when including the datadog tracing agent and the java library Redisson (https://github.com/redisson/redisson). If I exclude one of the two dependencies, then the compilation process works fine. Thanks for the support!

Using the latest version of GraalVM can resolve many issues.

GraalVM Version

java 17.0.12 2024-07-16 LTS Java(TM) SE Runtime Environment Oracle GraalVM 17.0.12+8.1 (build 17.0.12+8-LTS-jvmci-23.0-b41) Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 17.0.12+8.1 (build 17.0.12+8-LTS-jvmci-23.0-b41, mixed mode, sharing)

Operating System and Version

Darwin Kernel Version 23.6.0: Mon Jul 29 21:14:30 PDT 2024; root:xnu-10063.141.2~1/RELEASE_ARM64_T6000 arm64

Build Command

./mvnw -e clean native:compile -Pnative

Expected Behavior

I would expect the compilation process to succeed and generate a native image of my repo

Actual Behavior

The compilation fails at the step [2/8] Performing analysis

Steps to Reproduce

  1. git clone https://github.com/matteoluzzi/spring-boot-native-redisson.git
  2. ./mvnw -e clean native:compile -Pnative

Additional Context

I have tried to build the native image with metadata generated by the graavm tracing agent by passing the -H:DynamicProxyConfigurationFiles, -H:ReflectionConfigurationFiles, -H:ResourceConfigurationFile, -H:JNIConfigurationFiles and -H:SerializationConfigurationFiles, but getting the same error. I have included the generated *.json files in the sample project so it's possible to pass them to the build process by adding a <buildArg> at https://github.com/matteoluzzi/spring-boot-native-redisson/blob/main/pom.xml#L49

Build Log Output and Error Messages

[2/8] Performing analysis...  []                                                                        (20.2s @ 2.10GB)
  15,913 (83.25%) of 19,114 types reachable
  25,524 (53.79%) of 47,451 fields reachable
  87,336 (57.75%) of 151,236 methods reachable
   5,604 types,   480 fields, and 13,037 methods registered for reflection
       1 native library: -framework CoreServices

Fatal error: com.oracle.svm.core.util.VMError$HostedError: guarantee failed
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.shouldNotReachHere(VMError.java:72)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.guarantee(VMError.java:86)
	at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.ClassForNameSupport.registerClass(ClassForNameSupport.java:63)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.reflect.ReflectionDataBuilder.registerTypesForGenericSignature(ReflectionDataBuilder.java:726)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.reflect.ReflectionDataBuilder.registerTypesForGenericSignature(ReflectionDataBuilder.java:683)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.reflect.ReflectionDataBuilder.registerTypesForGenericSignature(ReflectionDataBuilder.java:677)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.reflect.ReflectionDataBuilder.registerTypesForClass(ReflectionDataBuilder.java:564)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.reflect.ReflectionDataBuilder.registerHeapDynamicHub(ReflectionDataBuilder.java:969)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.heap.SVMImageHeapScanner.onObjectReachable(SVMImageHeapScanner.java:155)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.heap.ImageHeapScanner.lambda$createImageHeapObject$5(ImageHeapScanner.java:396)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.heap.ImageHeapScanner.lambda$postTask$14(ImageHeapScanner.java:759)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:187)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:171)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1395)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)

matteoluzzi avatar Oct 05 '24 11:10 matteoluzzi

Hi @matteoluzzi,

Thank you for reaching out to us about this. We'll take a look into this shortly and I'll make sure to keep you updated.

selhagani avatar Oct 10 '24 16:10 selhagani

I was able to reproduce your issue. We will take a closer look into this and I'll keep you updated.

selhagani avatar Oct 14 '24 15:10 selhagani

Note that if I used the Liberica Native Image Kit then the compilation succeeds.

While the compilation might succeed in this case, I doubt that the underlying issue is fixed there. The error you see originates in this line: https://github.com/oracle/graal/blob/0ab0b8ee4f1e6e17156f91a9897c061512cb2a9f/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java#L63 Maybe in their version this check is patched out or the configuration metadata that gets used in that image build is different (thus preventing the registration to happen in the first place).

This VMError.guarantee(...) is what fails, if you try to register a fully-qualified classname for NI Class.forName-support with two different class objects. This can only happen if two different classes with the equal fully-qualified classname were loaded by two different classloader at image-builtime.

That is currently a fundamental limitation of native-image compared to regular Java. So far we are not able to lookup classnames at runtime from different classloaders. I.e. in the image there is only a single map from fully-qualified classname to class instance. If there are two different class objects with the same fully-qualified classname we cannot handle it.

For more info see WIP PR: https://github.com/oracle/graal/pull/9893

olpaw avatar Oct 16 '24 12:10 olpaw

Hi @olpaw, thanks for looking at this issue and explaining what is causing the error. From what I understood, both the Datadog agent and the Redisson library are registering the same fully qualified classname. Could it be possible to get which class is causing issue by adding some logs perhaps? As a workaround for my project, I noticed that if I swap the Redisson library for a spring data redis module I can at least compile my simplified project. Does that mean that I won't occur into the same issue at runtime?

Thanks again for the help!

matteoluzzi avatar Oct 20 '24 16:10 matteoluzzi

@matteoluzzi A suggestion in the meantime would be to use the micrometer with opentelemetry to send the data to datadog, remembering that javaagent generally has a negative impact on performance, when I used opentelemetry javaagent for example there was an average of 20% fewer requests processed in my applications used. micrometer with opentelemetry allows native compilation without major problems and also brings a gain in terms of memory and cpu usage compared to javaagent, of course the ideal is to do the test and validate that everything is needed is available in this module.

viniciusxyz avatar Nov 29 '24 22:11 viniciusxyz

From what I understand above, this is not something Native Image can solve. Closing for now.

wirthi avatar May 12 '25 13:05 wirthi