Spring让Java慢了30倍,JIT、AOT等让Java比Python快13倍,比C慢17%

比 Python 快 13 倍,比 C 慢 17%,Java 被骂慢骂了 20 年,原来是 Spring 的锅。

"Java 太慢了",类似这样的话,我听了快 10 年了。十年了我成长了,但有些人还在"刻舟求剑"。

今天,我在一个大佬的微信群里,看到又有人在讨论这个。说慢,又拿不出具体的数据,纯靠偏见在讨论。

上一次讨论类似问题,还是在月初。刚好有老外网友做了一个实验,对 62 门编程语言速度做了一个比较,通过莱布尼茨公式**计算 π 值,然后给出运行速度的排名,最慢是 Python (CPython)。实验过程和结果都公开透明,参见网址:https://github.com/niklas-heer/speed-comparison

有时候,我挺理解那些对 Java 有偏见的程序员的。比如,Python 程序员优雅地写下一行代码解决问题时,Java 还在吭哧吭哧地定义类和接口,当 js 在浏览器中快速执行时,Java 的应用可能还需要加载 Spring 上下文...

但这也不能说明 Java 就是慢。所以,今天,我想稍微花点时间,尝试为这些"偏见"找到源头,并用数据和原理告诉你:Java 不慢,慢的很可能是你的认知还停留在 20 年前

这些偏见,我都经历过

偏见 1 解释执行,肯定慢

这是最经典的误解。确实,Java 编译成字节码,再由 JVM 解释执行,中间多了一层。但你知道吗?现代 JVM 90% 的代码根本不走解释执行

甚至是在某些情况下,经过 JVM 充分的优化,Java 程序能比 C++ 程序更快。特别是在一些依赖 JVM 运行时分析和自适应优化的场景下。通过 JVM 的"即时编译"(JIT)和自适应优化能力,能在运行时做出静态编译语言难以实现的动态决策

偏见 2 GC STW 卡顿慢

Stop-The-World(STW)是 Java 程序员永远的痛。但这次我要说:你可能从来没用过真正的低延迟 GC

确实是没有任何一个商业化的 Java GC 能实现完全的零 STW,但目前主流的现代 GC,其设计核心都在于将 STW 时间缩短到极致,有些甚至能达到亚毫秒级别。

在某些分代的 JVM 中,其部分分代的 GC 并不需要 STW,也或者说是大部分 GC 阶段不需要 STW。并且,JVM 还推出了众多的优化手段,包括:多线程并行,并发标记/清理,全阶段并发 + 读屏障,着色指针和读屏障等。

偏见 3 启动慢,性能差

确实,一些企业级框架太过于笨重。尤其是,Spring + MyBatis + Dubbo,一套组合拳下来,启动 3 分钟,内存 2GB 起步。这印象太深了,以至于很多人把框架的臃肿等同于语言的低效

反射、AOP、bean 的顺序加载、连接池初始化等,它能不慢吗?但,这个慢,是框架造成的,并不是 Java 慢。

数据不会说谎

让我们来看一个文章开头所说的真实的基准测试。GitHub 项目 speed-comparisonhttps://niklas-heer.github.io/speed-comparison/使用莱布尼茨公式计算 π 值,在10 亿次迭代下,各语言表现如下。

语言 中位执行时间 与最快速度比值
C 7.08s 1.0x
Rust 7.11s 1.0x
Java (GraalVM) 7.33s 1.04x
C++ 8.16s 1.15x
Java (OpenJDK) 8.26s 1.17x
Go 10.4s 1.47x
Node.js 31.2s 4.41x
Python 113.17s 15.99x

Java 只比 C 慢 17%,但比 Python 快 13 倍!这个结果惊不惊讶?意不意外?

更扎心的是,在这个 CPU 密集型计算场景中,Python 甚至比 Node.js 还慢 3.6 倍。那些说Python 开发快就够了的人,可能没经历过计算密集型任务的绝望。

即使是 OpenJDK,也比 Go、PHP 等常见语言快。Github 上还有很多其它案例,我就不细说了,大家自己去看看吧。

为什么一些人会觉得 Java 慢?

根据我收集的资料和第一手经验,我觉得偏见主要来自以下几个层面。

排在第一个的是 Java 的历史债务。不少人印象里的 Java,是 JDK 1.4 的 Java,那个时候的 Java 确实慢。

  • 早期 JVM:纯解释执行,JIT 编译器形同虚设
  • 老旧的 GC:Serial GC 和 Parallel GC 动不动就 Full GC,停顿几秒
  • Applet** 噩梦:浏览器里那个卡顿的小程序,是整个 Java 生态的原罪

但现在是 2025 年!JDK 21、JDK 25 都出来了,ZGC 的停顿时间小于 1 毫秒,GraalVM 的 AOT 编译让启动速度快如闪电。他们的经验,也该更新了。

排在第二的应该是 JVM 中的技术迷雾,JVM 的"黑魔法"让你测不准。甚至是,只有 Java 面试才有调优,其它语言可能都没这么卷。

现代 JVM 太复杂了,复杂到连资深工程师都容易误判,看下面 3 个陷阱。

第一个陷阱就是 JIT** 的预热。

csharp 复制代码
// 你写的代码
public void calculate() { /* 复杂计算 */ }

// 实际执行路径
// 前 1000 次:解释执行 → 慢!
// 1000-10000 次:C1 编译 → 稍快
// 10000+ 次:C2 编译 + 激进优化 → 峰值性能!

很多人在预热阶段就下了"Java 好慢"的结论,根本没测到 JIT 优化后的真实性能。

第二个陷阱是 JVM 逃逸分析。

typescript 复制代码
public String process() {
    // 你以为:堆分配,GC 压力大
    StringBuilder sb = new StringBuilder(); 
    // 实际上:JVM 分析发现 sb 不会逃逸,直接栈分配,0 GC!
    return sb.toString();
}

JVM 的智能优化远超你的想象,但你用传统性能分析工具根本看不出来。

第三个陷阱是微基准测试骗局。

没有 JMH 的微基准测试都是耍流氓。JVM 会消除死代码循环展开内联虚方法等,你写的测试用例可能什么都没测到。。。

接下来是对 GC 的误解,源自于多数人根本不了解现代垃圾回收器。

  • ZGC(JDK 15+):停顿时间 < 1ms,支持 16TB 堆内存
  • Shenandoah:并发整理,吞吐量与低延迟兼得
  • G1:JDK 9 后的默认 GC,可预测的停顿模型

但大部分开发者还在用 JDK 8 的 Parallel GC,然后抱怨"GC 卡顿"。这不是 Java 的问题,这是你不升级的问题

然后是框架得背锅。慢的是 Spring,不是 Java。

我们来看一个真实案例。

java 复制代码
// 纯 Java 计算斐波那契数列
public long fib(int n) { /* 递归实现 */ } // 耗时:0.5ms

// Spring Bean 版本
@Service
public class FibService {
    @Cacheable
    public long fib(int n) { /* 同样实现 */ } // 耗时:15ms
}

Spring 的代理、AOP、事务、缓存一层层叠加,性能损耗可达 30 倍。但开发者往往把这笔账算在 Java 头上,而不是框架设计上。

反射是最大的元凶,而且到处是反射。Spring 依赖注入、MyBatis 动态代理、JSON 序列化,哪里都有反射。反射调用比直接调用慢50-100 倍,且完全无法被 JIT 优化。

说白了,不是 Java 慢,是你用的框架在"犯罪"。

最后是部署形态,容器时代的"水土不服"。

在 Kubernetes 时代,Java 确实显得格格不入。

  • 启动时间:JVM 加载 2000+ 核心类,Spring 扫描 500+ Bean,启动 30 秒起步
  • 内存占用:JVM 本身占 200MB,堆内存再分配 1GB,镜像臃肿
  • 资源感知:旧版 JVM 不认识 Docker 的 cgroup 限制,导致 OOM Kill

但这正是QuarkusMicronautSpring Native等要解决的问题。通过 AOT 编译和 GraalVM 原生镜像,Java 应用的启动时间可缩短至0.05 秒,内存占用降至30MB

Java 的真实性能定位

基于上述分析,Java 的真实性能画像应该是:

CPU 密集型,碾压 Python

CPU 密集型,接近 C++,碾压 Python。尤其是在科学计算、大数据处理(Hadoop/Spark)、高频交易(LMAX Disruptor)领域,Java 是事实标准。JIT 编译后的代码执行效率可达 C++ 的90% 以上

内存管理,全自动,高吞吐

虽然 GC 有开销,但对比手动内存管理(C++)或引用计数(Python),Java 的吞吐量优势在 多线程环境 下尤为明显。ZGC 的出现更补齐了低延迟短板。

并发编程,生态最成熟

JUC(java.util.concurrent)、Fork/Join 框架、虚拟线程等让 Java 的并发模型远超 Python 的 GIL 限制和 Node.js 的单线程。

当然,Java 也有不少短板的。

比如,冷启动。

Serverless 场景下,Python/Node.js 的毫秒级启动仍有优势。但 GraalVM 原生镜像已基本解决此问题。

再比如,内存占用,仍偏高了些。

即使优化后,JVM 的内存足迹仍大于 Go 或 Rust,这在边缘计算场景确实是劣势。

总结

真相很可能和某些群体想象的不一样,偏见是源于认知滞后。

Java 的"慢"是一个技术神话,其根源是:

  1. 时间差:用 2004 年的 Java 对比 2024 年的 Python
  2. 对象错:把 Spring 的慢当作 Java 的慢
  3. 测量错:在 JIT 预热阶段下结论
  4. 信息差:不知道 ZGC、GraalVM、Quarkus 的存在
  5. 定位差:Java 要和所有的语言比,却忽略了它的跨平台以及成熟的社区

作为技术人员,我们确实应该持续学习,要知道 JDK 每 6 个月一个版本,性能优化日新月异。

最后,我想说的是:Java 不慢了,慢的是你的技术栈该升级了。还是那多篇历史文章中说到的话,做个结尾吧。

相关推荐
颜酱2 小时前
单调栈:从模板到实战
javascript·后端·算法
神奇小汤圆2 小时前
支付成功订单却没了?MyBatis连接池的坑我踩了
后端
雨中飘荡的记忆4 小时前
OpenClaw:开源AI助手平台的革命之路
后端
程序员鱼皮4 小时前
GitHub 关注突破 2w,我总结了 10 个涨星涨粉技巧!
前端·后端·github
用户298698530144 小时前
程序员效率工具:Spire.Doc如何助你一键搞定Word表格排版
后端·c#·.net
爱分享的鱼鱼5 小时前
Spring Boot服务中添加字段的完整指南
后端
掘金者阿豪5 小时前
数据库选型的“第三维度”:为什么我们开始重新思考技术栈的底层逻辑
后端
SelectDB5 小时前
Doris & SelectDB for AI 实操:从零搭建非结构化数据智能分析洞察系统
后端
用户849359610535 小时前
OGORM 新手入门笔记
后端