背景

最近在做一个 JavaFX 桌面应用(数据可视化分析类),出于对新特性的尝鲜和长期维护考虑,技术栈直接拉到了最新的 JDK 25 + Kotlin 2.3 + JavaFX 25。结果就是,踩了一整圈版本对齐和模块系统的坑,记录一下。

版本必须严格对齐

这套组合对版本非常敏感,任何一个对不上都会报各种莫名其妙的错:

组件 版本 为什么必须是这个版本
JDK 25 JVM Target 统一为 25
Kotlin 2.3.0 第一个正式支持生成 Java 25 字节码的版本
Gradle 9.1+ 低版本 Gradle 不认 JDK 25
JavaFX 25.0.1 与 JDK 25 配套
IDEA 2025.3+ 旧版对 Kotlin 2.3 支持不全

Kotlin 版本低于 2.3 时,编译器无法把字节码目标设到 25,会直接报编译错误;Gradle 低于 9.1 时连 java.toolchain 都识别不了 JDK 25。这俩一旦对不上,报错信息往往指东打西,很难第一时间定位到是版本问题。

模块系统:–add-opens 是家常便饭

JavaFX 25 在强模块化下,大量内部包(com.sun.javafx.*)默认不开放反射。我们的图表组件深度用了 Chart 的内部渲染逻辑,不加 --add-opens 会直接抛 InaccessibleObjectException。运行参数长这样(节选):

--module-path .../javafx-sdk-25.0.1/lib
--add-modules javafx.controls,javafx.fxml,jdk.charsets,java.management
--add-opens javafx.controls/com.sun.javafx.charts=ALL-UNNAMED
--add-opens javafx.graphics/com.sun.javafx.iio=ALL-UNNAMED
--add-opens javafx.base/java.lang=ALL-UNNAMED
--add-opens javafx.controls/javafx.scene.chart=ALL-UNNAMED
--enable-native-access=javafx.graphics

几个印象深的点:

  • 只要碰了 com.sun.* 的内部 API,就老老实实 --add-opens,没有捷径。
  • --enable-native-access=javafx.graphics 在 25 里是硬性提示,不加会有警告甚至功能异常。
  • 开发期可以靠 IDEA 的 VM options 配,打包后要塞进启动脚本里。

渲染管线

桌面图表数据量大,我们强制走了软件渲染,避免某些显卡驱动下的花屏:

-Dprism.order=sw
-Dprism.maxvram=3G
-Djava.awt.headless=false

prism.order=sw 牺牲一点性能换稳定,对绘图密集型场景反而更可控,渲染结果不随用户机器的驱动版本漂移。

小结

生态还没完全跟上,版本对齐 + 模块开放这两件事得一次性配齐。配好之后基本就不用再动了,后续往里堆业务功能很顺。