Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LazyRandom for native code generation tools #85

Merged
merged 1 commit into from
Oct 25, 2023

Conversation

Maia-Everett
Copy link
Contributor

Trying to generate a native code image with GraalVM in code that uses TimeBasedEpochGenerator results in this exception:

Caused by: org.graalvm.compiler.java.BytecodeParser$BytecodeParserError: 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.
        at parsing com.fasterxml.uuid.impl.LazyRandom.sharedSecureRandom(LazyRandom.java:12)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.throwParserError(BytecodeParser.java:2518)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.throwParserError(SharedGraphBuilderPhase.java:110)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3393)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.handleBytecodeBlock(BytecodeParser.java:3345)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBlock(BytecodeParser.java:3190)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.build(BytecodeParser.java:1138)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:1030)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:97)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase.run(SharedGraphBuilderPhase.java:84)

This happens because the TimeBasedEpochGenerator constructor initializes the LazyRandom class unconditionally, even if it is never actually used because the constructor is never passed a null Random instance, and LazyRandom eagerly creates a SecureRandom instance in a static final field.

Changing the TimeBasedEpochGenerator constructor would break backward compatibility, so instead I have opted to modify LazyRandom so that SecureRandom initialization actually occurs lazily. With this, the code path that results in initializing LazyRandom.shared is never hit at code generation phase, and so native image generation works as expected.

@cowtowncoder
Copy link
Owner

Thank you @Maia-Everett for contributing this! I hope to review it soon, sounds like a useful improvement.


public static SecureRandom sharedSecureRandom() {
return shared;
// Double check lazy initialization idiom (Effective Java 3rd edition item 11.6)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is not called very often, I think I'll modify this to use straight synchronization instead of double-locking.

@cowtowncoder cowtowncoder merged commit a892069 into cowtowncoder:master Oct 25, 2023
2 checks passed
@cowtowncoder cowtowncoder changed the title Fix LazyRandom for native code generation tools Fix LazyRandom for native code generation tools Oct 25, 2023
@cowtowncoder cowtowncoder added this to the 5.0.0 milestone Feb 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants