You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pr@cassandra.apache.org by "lukasz-antoniak (via GitHub)" <gi...@apache.org> on 2025/10/21 13:19:00 UTC
[PR] Fix initialization of shaded Guava for GraalVM 25 [cassandra-java-driver]
lukasz-antoniak opened a new pull request, #2059:
URL: https://github.com/apache/cassandra-java-driver/pull/2059
Fixes [CASSJAVA-114](https://issues.apache.org/jira/browse/CASSJAVA-114).
Reproduction steps:
1. Checkout _main_ branch of https://github.com/spring-projects/spring-aot-smoke-tests
2. Remove workaround applied in https://github.com/spring-projects/spring-aot-smoke-tests/commit/8b99eb7fc811eca37d3fc8682651fbd623d869b4
3. Update `data/data-cassandra-reactive/build.gradle` with:
```
repositories {
mavenLocal()
}
configurations.all {
resolutionStrategy {
force("org.apache.cassandra:java-driver-core:4.19.1-SNAPSHOT")
force("org.apache.cassandra:java-driver-guava-shaded:4.19.1-SNAPSHOT")
force("org.apache.cassandra:java-driver-query-builder:4.19.1-SNAPSHOT")
}
}
```
4. Apply changes locally to Java driver and install it in local Maven repository.
5. Run Gradle build to check the fix:
```
./gradlew clean :data:data-cassandra-reactive:nativeCompile --rerun-tasks
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For additional commands, e-mail: pr-help@cassandra.apache.org
Re: [PR] Fix initialization of shaded Guava for GraalVM 25 [cassandra-java-driver]
Posted by "absurdfarce (via GitHub)" <gi...@apache.org>.
absurdfarce commented on PR #2059:
URL: https://github.com/apache/cassandra-java-driver/pull/2059#issuecomment-4007528533
So... I'm a little skeptical about this as a default approach for the Java driver.
I can reproduce this problem using GraalVM 25 on the Spring AOT smoke test repo specified by @lukasz-antoniak above. If it were a widespread problem I should see it elsewhere, though, and I absolutely _cannot_ reproduce this with the cassandra-quarkus native tests... which seems strange. Seems like understanding the nature of that difference in behaviour is pretty important here.
Stepping back a bit, why would Graal be attempting to initialize this class at build time at all? The target class for the substitution is com.google.common.primitives.UnsignedBytes.LexicographicalComparatorHolder which is only referenced in [ByteOrderedToken](https://github.com/apache/cassandra-java-driver/blob/4.19.2/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/token/ByteOrderedToken.java#L60-L66) as far as I can tell. Instances of that class are provided by a factory impl that's determined by [a registry](https://github.com/apache/cassandra-java-driver/blob/4.19.2/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/token/DefaultTokenFactoryRegistry.java#L36-L52). In normal driver operation that registry determines which token factory to return based on the contents of system.local... so you'd only actually need this class at runtime if you were using that partitioner. There's no way to determine that at build time, however, so it makes sen
se that this class would be initialized at runtime as you would normally expect.
In short: I don't understand why the Spring smoke tests are triggering something in GraalVM that's trying to do a build-time class initialization. This seems like it might be situation-dependent behaviour, and if that's the case a fix in the Spring AOT smoke test repo is absolutely the correct way to handle this situation.
So I guess I'm not convinced we should add this as a general config for _all_ GraalVM clients using the Java driver.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For additional commands, e-mail: pr-help@cassandra.apache.org
Re: [PR] Fix initialization of shaded Guava for GraalVM 25 [cassandra-java-driver]
Posted by "lukasz-antoniak (via GitHub)" <gi...@apache.org>.
lukasz-antoniak commented on PR #2059:
URL: https://github.com/apache/cassandra-java-driver/pull/2059#issuecomment-4010999984
@absurdfarce: Are you building Quarkus with GraalVM 25?
The issue seems that `com.datastax.oss.driver.shaded.guava.common.primitives.LexicographicalComparatorHolderSubstitution` is being initialized at build time, and references `UnsignedBytes.LexicographicalComparatorHolder.PureJavaComparator` which is not initialized at build time (comes from shaded Guava, but not from source folder). `LexicographicalComparatorHolderSubstitution` is our class that is part of shaded Guava JAR in the end, but it is present in source directory.
For reference, below is the error message I get when building the example application without proposed fix:
```
Fatal error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: An object of type 'com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' was found in the image heap. This type, however, is marked for initialization at image run time for the following reason: classes are initialized at run time by default.
This is not allowed for correctness reasons: All objects that are stored in the image heap must be initialized at build time.
You now have two options to resolve this:
1) If it is intended that objects of type 'com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' are persisted in the image heap, add
'--initialize-at-build-time=com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator'
to the native-image arguments. Note that initializing new types can store additional objects to the heap. It is advised to check the static fields of 'com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' to see if they are safe for build-time initialization, and that they do not contain any sensitive data that should not become part of the image.
2) If it is not intended that objects of type 'com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' are persisted in the image heap, examine the stack trace and use
'--initialize-at-run-time=com.datastax.oss.driver.shaded.guava.common.primitives.LexicographicalComparatorHolderSubstitution'
to prevent instantiation of the culprit object.
The culprit object has been instantiated by the 'com.datastax.oss.driver.shaded.guava.common.primitives.LexicographicalComparatorHolderSubstitution' class initializer with the following trace:
at com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator.<init>(UnsignedBytes.java:417)
at com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator.<clinit>(UnsignedBytes.java:418)
at com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes.lexicographicalComparatorJavaImpl(UnsignedBytes.java:279)
at com.datastax.oss.driver.shaded.guava.common.primitives.LexicographicalComparatorHolderSubstitution.<clinit>(LexicographicalComparatorHolderSubstitution.java:31)
If you are seeing this message after upgrading to a new GraalVM release, this means that some objects ended up in the image heap without their type being marked with --initialize-at-build-time.
To fix this, include '--initialize-at-build-time=com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' in your configuration. If the classes do not originate from your code, it is advised to update all library or framework dependencies to the latest version before addressing this error.
The following detailed trace displays from which field in the code the object was reached.
Object was reached by
reading static field com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder.BEST_COMPARATOR
at com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes.lexicographicalComparator(UnsignedBytes.java:274)
parsing method com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes.lexicographicalComparator(UnsignedBytes.java:274) reachable via the parsing context
at com.datastax.oss.driver.internal.core.metadata.token.ByteOrderedToken.compareTo(ByteOrderedToken.java:64)
at com.datastax.oss.driver.internal.core.metadata.token.ByteOrderedToken.compareTo(ByteOrderedToken.java:29)
at java.util.TreeMap.put(TreeMap.java:848)
at com.oracle.svm.core.code.FactoryMethodHolder.LocaleExtensions_OLKh1W5hrPDlwtlgvsFehG(generated:0)
at sun.util.locale.InternalLocaleBuilder.getLocaleExtensions(InternalLocaleBuilder.java:533)
at java.util.Locale.getDefaultExtensions(Locale.java:1181)
at java.util.Locale.initDefault(Locale.java:1157)
at com.oracle.svm.core.jdk.localization.substitutions.Target_java_util_Locale$DefaultLocaleAccessors.get(Target_java_util_Locale.java:51)
at java.util.Locale.initDefault(Locale.java:1162)
at java.util.Locale.getDisplayLocale(Locale.java:1137)
at java.util.Locale.getDefault(Locale.java:1121)
at com.oracle.svm.core.code.FactoryMethodHolder.Formatter_dUcv0u89qA5jjO5C6NRf2B(generated:0)
at com.oracle.svm.enterprise.core.stringformat.a.a(stripped:252)
at com.oracle.svm.enterprise.core.stringformat.a.a(stripped:137)
at org.springframework.boot.logging.CorrelationIdFormatter.of(CorrelationIdFormatter.java:138)
at org.springframework.boot.logging.CorrelationIdFormatter.<clinit>(CorrelationIdFormatter.java:73)
at static root method.(Unknown Source)
at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.heap.ImageHeapScanner.onObjectReachable(ImageHeapScanner.java:618)
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.heap.SVMImageHeapScanner.onObjectReachable(SVMImageHeapScanner.java:127)
at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.heap.ImageHeapScanner.lambda$markReachable$0(ImageHeapScanner.java:589)
at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:166)
at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:152)
at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1750)
at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(ForkJoinTask.java:1742)
at java.base/java.util.concurrent.ForkJoinTask$InterruptibleTask.exec(ForkJoinTask.java:1659)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:511)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1450)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2019)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:187)
Caused by: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: An object of type 'com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' was found in the image heap. This type, however, is marked for initialization at image run time for the following reason: classes are initialized at run time by default.
This is not allowed for correctness reasons: All objects that are stored in the image heap must be initialized at build time.
You now have two options to resolve this:
1) If it is intended that objects of type 'com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' are persisted in the image heap, add
'--initialize-at-build-time=com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator'
to the native-image arguments. Note that initializing new types can store additional objects to the heap. It is advised to check the static fields of 'com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' to see if they are safe for build-time initialization, and that they do not contain any sensitive data that should not become part of the image.
2) If it is not intended that objects of type 'com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' are persisted in the image heap, examine the stack trace and use
'--initialize-at-run-time=com.datastax.oss.driver.shaded.guava.common.primitives.LexicographicalComparatorHolderSubstitution'
to prevent instantiation of the culprit object.
The culprit object has been instantiated by the 'com.datastax.oss.driver.shaded.guava.common.primitives.LexicographicalComparatorHolderSubstitution' class initializer with the following trace:
at com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator.<init>(UnsignedBytes.java:417)
at com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator.<clinit>(UnsignedBytes.java:418)
at com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes.lexicographicalComparatorJavaImpl(UnsignedBytes.java:279)
at com.datastax.oss.driver.shaded.guava.common.primitives.LexicographicalComparatorHolderSubstitution.<clinit>(LexicographicalComparatorHolderSubstitution.java:31)
If you are seeing this message after upgrading to a new GraalVM release, this means that some objects ended up in the image heap without their type being marked with --initialize-at-build-time.
To fix this, include '--initialize-at-build-time=com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes$LexicographicalComparatorHolder$PureJavaComparator' in your configuration. If the classes do not originate from your code, it is advised to update all library or framework dependencies to the latest version before addressing this error.
The following detailed trace displays from which field in the code the object was reached.
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.classinitialization.ClassInitializationFeature.checkImageHeapInstance(ClassInitializationFeature.java:205)
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.SVMHost.validateReachableObject(SVMHost.java:371)
at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.heap.ImageHeapScanner.onObjectReachable(ImageHeapScanner.java:607)
... 11 more
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For additional commands, e-mail: pr-help@cassandra.apache.org
Re: [PR] Fix initialization of shaded Guava for GraalVM 25 [cassandra-java-driver]
Posted by "absurdfarce (via GitHub)" <gi...@apache.org>.
absurdfarce commented on PR #2059:
URL: https://github.com/apache/cassandra-java-driver/pull/2059#issuecomment-4014389285
You have it basically correct @lukasz-antoniak. To be very specific I make the following claims:
* I am able to reproduce the build failure with the spring-aot-smoke-tests repo locally using GraalVM 25.x via the process described above
* If I then change over to a local checkout of cassandra-quarkus and run `mvn verify -P native` (also using the same GraalVM 25.x install) I do _not_ see any errors
I also completely agree with your analysis. LexicographicalComparatorHolderSubstitution was added to the shaded Guava JAR as part of work done on [JAVA-2799](https://datastax-oss.atlassian.net/browse/JAVA-2799). The substitution isn't limited by any conditional checks so it should be in play for any GraalVM app using the Java driver. So if this were _just_ a failure of how the Java driver manages Graal configs we should see it everywhere... and we very clearly do not.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: pr-unsubscribe@cassandra.apache.org
For additional commands, e-mail: pr-help@cassandra.apache.org