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

Disallow Random/SplittableRandom in the image heap and initialize relevant classes at runtime #2993

Closed
wants to merge 7 commits into from
Closed

Disallow Random/SplittableRandom in the image heap and initialize relevant classes at runtime #2993

wants to merge 7 commits into from

Conversation

pivovarit
Copy link
Contributor

@pivovarit pivovarit commented Nov 18, 2020

Disallowing Random and SplittableRandom presence in the image heap since it can result in undesired side-effects.

The "failure" happens at run time but is caused by an unwanted build-time initialization of one class which results in unwanted caching.


Reproducer:

echo "public class Hello { public static void main(String[] args) { System.out.println(StrictMath.random()); }}" >> Hello.java
javac Hello.java
native-image Hello

and then the fun begins:

❯ ./hello  
0.7712305575721234
❯ ./hello  
0.7712305575721234
❯ ./hello  
0.7712305575721234

@graalvmbot
Copy link
Collaborator

Hello Grzegorz Piwowarek, thanks for contributing a PR to our project!

We use the Oracle Contributor Agreement to make the copyright of contributions clear. We don't have a record of you having signed this yet, based on your email address gpiwowarek -(at)- gmail -(dot)- com. You can sign it at that link.

If you think you've already signed it, please comment below and we'll check.

@vjovanov
Copy link
Member

@pivovarit thanks for fixing this! I am wondering does the failure happens at build-time or at runtime?

I think we should really detect this case at build-time.

@vjovanov
Copy link
Member

Could you please sign the OCA and we can merge?

@vjovanov
Copy link
Member

I can't think of case where one would like to have a Random initialized at build-time, but I can think of a million cases where one dosn't want to do that.

Can we add a check to DisallowedImageHeapObjects that verifies that RandomNumbers don't end up in the heap?

@christianwimmer @cstancu do you see a reason not to disallow Random in the image heap?

@pivovarit
Copy link
Contributor Author

The only reason I could think of was demoing the unwanted side-effects of build-time initialization.

As soon as I get a green light, I'll add it to disallowed objects.

@christianwimmer
Copy link

Thanks for detecting this issue.

And yes, we should disallow instances of Random and SplittableRandom in the image heap. Better to fail at image build time than to have non-random values at run time.

@pivovarit pivovarit changed the title Initialize java.lang.StrictMath$RandomNumberGeneratorHolder at runtime Disallow Random/SplittableRandom in the image heap and initialize java.lang.StrictMath$RandomNumberGeneratorHolder at runtime Nov 22, 2020
@pivovarit
Copy link
Contributor Author

pivovarit commented Nov 22, 2020

@pivovarit pivovarit changed the title Disallow Random/SplittableRandom in the image heap and initialize java.lang.StrictMath$RandomNumberGeneratorHolder at runtime Disallow Random/SplittableRandom in the image heap and initialize relevant classes at runtime Nov 22, 2020
@vjovanov
Copy link
Member

Can't wait to run tests to see what other bugs we found :)

@@ -55,6 +58,13 @@
}

public static void check(Object obj, DisallowedObjectReporter reporter) {
/* Random/SplittableRandom can not be in the image heap. */
if (((obj instanceof Random) && !(obj instanceof ThreadLocalRandom)) || obj instanceof SplittableRandom) {
Copy link
Member

Choose a reason for hiding this comment

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

Thoughtfull--thanks!

Copy link
Member

@vjovanov vjovanov left a comment

Choose a reason for hiding this comment

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

LGTM. Running the tests now.

@pivovarit
Copy link
Contributor Author

OCA signed. Got a confirmation from Dalibor

@pivovarit
Copy link
Contributor Author

@vjovanov any results yet?

@vjovanov
Copy link
Member

Yes, it has discovered a few issues in the internal tests. I will merge this until the end of the year. Is that OK?

@pivovarit
Copy link
Contributor Author

Sure!

@vjovanov
Copy link
Member

Will merge it in the next day or two (due to failing tests in downstream projects). Will make a backport PR without the strict check to 23.1. Hope it makes it.

@zakkak
Copy link
Collaborator

zakkak commented Feb 1, 2021

This has been merged in a975ef5 and backported to 20.3.1 in 19298b7

@pivovarit pivovarit closed this Feb 1, 2021
@pivovarit pivovarit deleted the runtime-init-strict-math branch February 1, 2021 17:37
@jas88
Copy link

jas88 commented Feb 22, 2022

I can't think of case where one would like to have a Random initialized at build-time, but I can think of a million cases where one dosn't want to do that.

I happened to come across this thread working on exactly such a case - I'm trying to build a text parsing tool which uses a library which happens to use a SplittableRandom somewhere in its internal data structures. No interest at all in making the values non-deterministic across runs - indeed probably slightly preferably not to - but very interested in being able to use the library from compiled code, and pre-building the lookup table rather than re-doing it each startup. Would it be possible to suppress this check for such cases please? --DisableRandomChecks or similar, if there isn't already an analogous option somewhere.

@pivovarit
Copy link
Contributor Author

@jas88 why would you ever want to do that? this is also how standard JVM behaves by default

@jas88
Copy link

jas88 commented Feb 22, 2022

@pivovarit When did the standard JVM start precompiling to native executables at all, let alone with filtering whether or not you've used a pseudo-random number? What you described at the start of this thread as "undesired side-effects" is entirely harmless for my use case (arguably beneficial in some ways), unlike the compilation failure I'm dealing with as a result of this patch.

If the behaviour involved _Secure_Random (which implies the caller actually needs something genuinely non-predictable), or a situation where you genuinely want non-deterministic "randomness", fair enough, but I for one want code that actually compiles and works rather than a spurious error message.

Presumably the best workaround for my case in the mean time is to pin to building with Graal 21.3.0? I could try sending a patch upstream to that library to remove the use of SplittableRandom when loading as a longer term fix for my case.

@pivovarit
Copy link
Contributor Author

Are you sure your code is not compiling due to this patch? At the time of implementation, it was just changing the runtime behaviour and not rejecting anything that uses SplittableRandom (and any other Random)

@jas88
Copy link

jas88 commented Feb 22, 2022

I was getting a compilation error: 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.

IMO that should be a warning rather than an error?

Reverting to 20.3.0 gets past this build stage at least, but fails in compiling some glue code in PosixDirectives.c which seems unrelated. I'll try building a newer GraalVM from source with this check removed at some point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants