blog podcast

Quarkus and Randomness

Quarkus is a project in the JVM world which enables you to write “Supersonic Subatomic Java” programs. When one first starts looking into the project it can feel a bit fuzzy what it actually does. The end result though is pretty clear, you get java application that have a significantly smaller memory footprint and that startup a lot faster. These are two features that makes Quarkus great for the Native environment where you typically want you applications to be able to scale up and down quickly and not take more resources than necessary.

But as with most great things in Software, these abilities comes with a trade off. To achieve it’s (quite incredible) performance boost Quarkus moves computations from the Runtime into the Build Time, especially when you are running the applications as native. To achieve this it has to remove of some features. It for example assumes a “Closed World” application and disables relfections unless you actively white list classes for reflection usage. It also executes blocks of static code when it is compiling already.

This last trick is what I wanted to talk about here. Because another feature that seasoned Java developers will know of is that you usually want to run your application with a -Djava.security.egd=/dev/urandom. What does that mean? Well, Baeldung has written a good article on it here. If you look at chapter 10 on the linked page you’ll see that the default value is /dev/random, which is then used to get random values for your application. The problem is that if you have a machine where not much user input is coming (like a virtual machine, or a server), calling /dev/random to get random values will simply block your process. So it just hangs.

Now this is where you need to pay attention. Looking into the java code for package sun.security.provider.SunEntries you’ll find this snippet:

    static {
        seedSource = AccessController.doPrivileged(
                new PrivilegedAction<String>() {

            @Override
            public String run() {
                String egdSource = System.getProperty(PROP_EGD, "");
                if (egdSource.length() != 0) {
                    return egdSource;
                }
                egdSource = Security.getProperty(PROP_RNDSOURCE);
                if (egdSource == null) {
                    return "";
                }
                return egdSource;
            }
        });

        DEF_SECURE_RANDOM_ALGO  = (NativePRNG.isAvailable() &&
            (seedSource.equals(URL_DEV_URANDOM) ||
             seedSource.equals(URL_DEV_RANDOM)) ?
            "NativePRNG" : "DRBG");
    }

As you can see the java.security.egd property is used in a static block. This means that for Quarkus, this property will be initialized at build time and not at runtime. Which means that it doesn’t matter if you run your Quarkus application with the java.security.egd flag or not, from the perspective of the SunEntries class this code has already been executed.

The consequence might be that you’ll get blocking code when trying to use the SecureRandom string class.

So what can you do about it? Well, you’ll just have to make sure that the build time runs with the flag. You can do this by using quarkus.native.additional-build-args=-Djava.security.egd=file:/dev/urandom in your application.properties file. This will now make your native application use /dev/urandom.