跳到主要内容

吐槽一下GraalVM, 来自今天尝试把Spring响应式编程+Spring Native+mongoReactive缝合在一起

不得不说,每次使用Native-Image编译为可执行程序后,我心里就没底,在想,自己会不会又引入了什么不能引入的包导致构建失败,会不会引入的第三方包中又存在awt的引用,或者反射的使用。。。

每每这时总是会想起Rust构建的爽快,不用担心这些问题。但是Rust的开发速度又是让我觉得很不爽的一点,写起来比起已经写了很久的Java总是差点意思。

而现在都已经2023了,在使用全响应式编程Spring Native+mongodb构建后端服务时,但是得到的结果仍然是让人相当不愉快的。碰到了一系列的问题,而这些问题又是那种你不知道如何下手去解决的,如果有人看到这篇文章并且知道解决方案务必留言一下 (最后还是解决了,只是改了个配置,在这:【已解决】GraalVM mongodb-reactive SpringNative,Java能正常运行,但是编译出的...)

接下来吐槽一下在使用一些令人很不爽的点

编译时CPU被占满以及时间的漫长

我的电脑配置是:Apple M1 16 GB 13.4 Ventura系统

这是某次使用maven native compile得到的结果

你可以看到消耗的时间超过3分钟,编译时的CPU占用是吃满的,而且整个过程内存占用也是相当之大,我的电脑一直是处在一个烫手的状态,一点也让人愉快不起来。

补一张编译时的温度监控截图

Java代码不再是一次编写到处运行

我可以接受每个设备都安装GraalVM进行编译,这也顶多是安装一个JDK的难度,最不济还有Docker帮我们解决这些问题。但是我不能接受写完代码后,编译通过了,但是执行不了,也无法排查是哪里的问题,然后回过头来尝试“移除某些依赖”,“升级某个依赖的版本”,“改变某段代码的写法”,“花费大量的时间搜索是否有人碰到同样的问题”等等等一系列的操作。

大家写Java本身就是因为Java有丰富的社区,成熟的解决方案,这样你随时都可以拿出一个不算太差的类库缝合在一起,组成一个初代的产品,然后推出。但是很明显GraalVM是破坏了这种体验的,你没法知道自己用的类库行不行,自己写的代码是不是还需要修改,而在编译后得到的可执行程序测试再得到的结果去修改原有的设计本身就是一种破坏,为此你需要花费更多的时间去思考兼容性,代码的健壮性,以及搜索替代方案的然后重新对整个架构进行思考。

至少GraalVM下的Spring Native和Quarkus都还没有达到开箱即用的状态,这里不讨论写个hello world的情况。 而眼看Rust那边都已经在多个领域发光发热,甚至还能交叉编译,着实让人羡慕,我期望的是能用Java的写法,然后能做到覆盖Rust差不多的编译场景,至少三大主流的linux,macos,windows都能享受到,也不要求要Rust的性能,能维持和JVM下相同的性能都已经算是奢求了。

问题解决的困难度骤然提升

以前Java代码写错了,你在网上搜搜大部份博客其实都写到了,甚至现在还有chatGPT,它的资料覆盖了Java开发80%的场景,你只需要不停的追问它,得到合适的解决方案即可。

但是当GraalVM编译出错,你要解决这个错误可就不是这么简单了,首先你会去谷歌搜索,看看有没有人碰到和你一样的问题,运气好的话已经有人踩过坑了,然后你一看issues时间,怎么还是2018的问题,不过还好状态是已经closed,说明肯定有人解决了,然后根据给的内容,尝试更换GraalVM JDK版本或是更改什么设置,这是理想的场景了。

但是更多的是,没人碰到过你的问题,chatGPT也不知道,去GraalVM提交issues不知道什么才会有回复,比如现在面对的这个问题,Java版本的代码是完全没问题的,编译也可以通过,但是使用可执行程序进行连接mongo就会抛AuthenticationFailed的问题,我在网上搜了一圈,只找到一个和我类似问题,而且那个老哥的问题还是帐号密码写错了。

这些体验下来,属实是劝退我接着使用Spring Native,你会对你写的代码心里没底,不知道最后1+1能不能=2,这个问题只有编译成功+运行成功才算是成功的第一步。毕竟你还不知道如果运行一段时间会不会有问题呢。如果你用的是响应式编程+GraalVM,那么排查错误的时候,你会体验到既没有调用栈打印,和打印了但是打印到Native方法去的“爽快感”,爽快的想让人直接放弃治疗。

不如转战Rust

GraalVM的设想是真的好,我也真的希望可以把工业糖精kotlin+GraalVM+响应式编程缝合在一起,得到一个启动快,占用小,性能高的可执行程序,又或是大部份逻辑用Java写,和系统操作的逻辑用Rust写,然后通过GraalVM调用Rust写的。

但是实际体验实在是让我觉得有点过于理想了,加之国内做这个的好像都还没有几个,大多数企业还是抱着JDK8在玩,要真有那么一天估计也是很久很久以后了,不如先学学Rust,真香!