Quarkus 打包native报错 随机数种子不符合预期 | 8月更文挑战

884 阅读2分钟

Quarkus 是一个目前非常火的 Java 应用开发框架,定位是轻量级的微服务框架。Quarkus 提供了优秀的容器化整合能力,相较于传统开发框架(Spring Boot)有着更快的启动速度、更小的内存消耗、更短的服务响应。

通过 GraalVM 将 Quarkus 项目打包为 native运行程序,即可以实现项目的快速启动,达到秒级甚至为毫秒级。

但在使用过程中也同样有着一定的约束,比如——随机数。在原来将项目打包成jar的方式时,类的加载和初始化会在程序运行时才进行执行,比如java.util.Random类中的随机种子的生成会在程序真正运行并进行初始化时才会生成。但GraalVM 将 Quarkus 项目打包为 native运行程序时,会直接将类中的静态属性直接进行初始化操作,而不是等待程序运行时。

假如你恰巧在类的静态属性中定义并创建了java.util.Random对象

private static final Random RANDOM = new Random();

那么你将会报如下错误:

image.png 此时就是由于在GraalVM打包时会初始化Random对象和随机种子,同时又校验到不允许这样进行编码。

对于该问题的解决办法官方给了两种: 1、首先是他建议你修改代码逻辑,不要对类静态属性中的Random对象进行初始化。通过使用单例模式来实现对象的初始化和使用。

public class RandomUtil {

    private static Random random;

    public static Random get() {
        if (random == null) {
            synchronized (RandomUtil.class) {
                if (random == null) {
                    random = new Random();
                }
            }
        }
        return random;
    }
}

2、如果你不希望修改你的写法,或者出现问题的是第三方的jar包,你无法对源码进行修改,那么官方也提供了在运行时在进行初始化的方式。你只要指定需要在运行时才进行初始化的类,就可以解决这个问题。 在 application.properties 文件中增加配置:

# 延迟初始化org.apache.commons.lang3.RandomStringUtils类
quarkus.native.additional-build-args=--initialize-at-run-time=org.apache.commons.lang3.RandomStringUtils

注意,在这里写的是包含Random静态属性的类,而不是Random类。

其实Quarkus官方自身也遇到了这个问题,而他们是通过编码的方式解决的,而不是通过参数配置。 Merge pull request #16008 from zakkak/grpc-random-reinit
所以在实际使用中你也可以有第三种解决办法,就是像官方一样通过编码来解决问题。


最后,感谢你的阅读。愿你的人生了无Bug。