You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 17环境下Quarkus集成OptaPlanner时参数化单元测试正常运行但热重载失效的配置方案咨询

Java 17下Quarkus+OptaPlanner参数化测试与热重载兼容方案

最近把JDK升级到17后,在Quarkus项目里跑OptaPlanner的参数化单元测试时踩了个坑:
一开始直接抛出InaccessibleObjectException,提示模块java.base没把java.util开放给未命名模块,导致XStream的TreeSetConverter初始化失败,参数化测试全挂。

我一开始把--add-opens相关参数一股脑加到了quarkus-maven-plugin的compilerArgs、jvmArgs,还有maven-surefire-plugin、native环境的maven-failsafe-plugin的argLine里,结果参数化测试能正常跑了,但Quarkus的热重载功能直接失效了——修改代码后重启Quarkus时,居然报invalid flag错误,把我整懵了。

问题根源

后来才搞明白:--add-opens和--enable-preview是JVM运行时参数,不是Java编译器的参数!我之前把这些参数塞到了quarkus-maven-plugin的compilerArgs里,而compilerArgs是给javac编译器用的,编译器根本不认这些JVM启动参数,热重载时Quarkus会调用编译器,自然就报错了。

解决配置方案

核心思路就是拆分参数类型:编译器参数只放编译相关的,JVM运行参数只放在JVM启动相关的配置节点里。

1. 调整Quarkus Maven插件配置

把compilerArgs里的--add-opens参数全部移除,只保留编译需要的参数(比如--enable-preview,如果你的项目用了Java预览特性的话),jvmArgs里保留所有JVM运行时需要的参数:

<plugin>
    <groupId>${quarkus.platform.group-id}</groupId>
    <artifactId>quarkus-maven-plugin</artifactId>
    <version>${quarkus.platform.version}</version>
    <extensions>true</extensions>
    <configuration>
        <source>${maven.compiler.source}</source>
        <target>${maven.compiler.target}</target>
        <!-- 编译器参数只保留编译相关的,移除所有--add-opens -->
        <compilerArgs>
            <arg>--enable-preview</arg>
        </compilerArgs>
        <!-- JVM运行参数保留所有需要的--add-opens和--enable-preview -->
        <jvmArgs>--enable-preview --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED</jvmArgs>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>build</goal>
                <goal>generate-code</goal>
                <goal>generate-code-tests</goal>
            </goals>
        </execution>
    </executions>
</plugin>

2. 保留测试插件的参数配置

maven-surefire-plugin和native环境的maven-failsafe-plugin的argLine配置不变,因为这些是给测试运行时的JVM用的,没问题:

<!-- maven-surefire-plugin 配置 -->
<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>${surefire-plugin.version}</version>
    <configuration>
        <argLine> --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED </argLine>
        <systemPropertyVariables>
            <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
            <maven.home>${maven.home}</maven.home>
        </systemPropertyVariables>
    </configuration>
</plugin>

<!-- Native Profile 里的 maven-failsafe-plugin 配置 -->
<profiles>
    <profile>
        <id>native</id>
        <activation>
            <property>
                <name>native</name>
            </property>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <version>${surefire-plugin.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>integration-test</goal>
                                <goal>verify</goal>
                            </goals>
                            <configuration>
                                <argLine> --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED </argLine>
                                <systemPropertyVariables>
                                    <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
                                    <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
                                    <maven.home>${maven.home}</maven.home>
                                </systemPropertyVariables>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
        <properties>
            <quarkus.package.type>native</quarkus.package.type>
        </properties>
    </profile>
</profiles>

3. 额外说明

如果你的项目没有用到Java预览特性,可以直接把--enable-preview参数从所有配置里移除,进一步简化配置。

效果验证

调整完配置后:

  • OptaPlanner的参数化单元测试可以正常运行,反射权限问题解决;
  • Quarkus的热重载功能恢复正常,修改代码后重启不再报无效flag错误;
  • 非参数化的简单测试依然不需要额外配置就能正常工作。

内容的提问来源于stack exchange,提问作者minioim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 19:22:43