-server 是什么?
-server 是一个 Java 虚拟机 (JVM) 的启动模式参数,它告诉 JVM 以“服务器模式”来运行,而不是默认的“客户端模式”(Client Mode)。

这个参数的核心作用是改变 JVM 的内存分配策略和垃圾回收器的默认选择,以换取更高的运行性能,但代价是更长的启动时间和更大的初始内存占用。
两种模式的区别 (Client vs. Server)
理解 -server 的关键在于理解它与 -client(或默认模式)的区别,这种差异主要体现在编译器和内存管理上。
| 特性 | 客户端模式 (-client) |
服务器模式 (-server) |
|---|---|---|
| 目标 | 快速启动,占用内存少,适合桌面应用、测试、开发。 | 最大化长期运行性能,启动慢,占用内存多,适合后端服务、应用服务器。 |
| JIT 编译器 | 使用 C1 编译器,它编译速度快,但生成的代码优化级别较低。 | 使用 C2 编译器 (也称为 HotSpot Server Compiler),它编译速度慢,但会进行更深层次的优化(如方法内联、循环展开等),生成更高效的本地代码。 |
| 默认堆大小 | 较小,在 64 位 JDK 8 中,默认可能是 1/4 的物理内存,但有下限(如 128MB)。 | 较大,在 64 位 JDK 8 中,默认通常是 1/4 的物理内存,但有更高的下限(如 1GB)。 |
| 默认垃圾回收器 | Serial GC (串行垃圾回收器),单线程,暂停时间长,但管理简单,适合小内存应用。 | Parallel GC (并行垃圾回收器),多线程进行垃圾回收,充分利用多核 CPU,吞吐量高。 |
| 适用场景 | IDE、小工具、需要快速启动的脚本、测试环境。 | Web 服务器、应用服务器(如 Tomcat, JBoss)、大数据处理(如 Hadoop, Spark)、所有需要7x24小时运行的服务。 |
-server 的具体影响
当你使用 java -server ... 启动你的 Java 应用时,会发生以下几件事:
-
启用 C2 JIT 编译器:
(图片来源网络,侵删)- JVM 会投入更多资源来分析和编译热点代码(频繁执行的代码)。
- 编译后的代码执行效率远高于 C1 编译器或解释执行的代码。
- 这会导致应用的“预热时间”(Warm-up Time)变长,在预热期间,性能可能并不理想,因为代码还在被编译和优化,预热完成后,性能会达到顶峰。
-
增加初始堆内存:
JVM 会分配一个更大的初始堆空间,这可以减少应用在运行初期因堆空间不足而触发频繁的 Minor GC,从而提升稳定性。
-
选择 Parallel GC 作为默认垃圾回收器:
- Parallel GC 专注于最大化应用程序的吞吐量(Throughput),即 CPU 用于执行用户代码的时间比例。
- 它使用多个线程来并行清理新生代和老年代,能很好地利用现代服务器的多核 CPU。
- 但它的缺点是可能会产生较长的 "Stop-The-World" (STW) 暂停,因为垃圾回收时所有应用线程都会被停止。
如何使用?
非常简单,只需在 java 命令后加上 -server 即可。
示例:
# 启动一个名为 MyServerApp 的 Java 应用,并使用服务器模式 java -server -jar MyServerApp.jar # 或者指定主类 java -server com.example.MainClass
注意:
- 在现代 JDK 版本(如 JDK 8 及以后)的 HotSpot JVM 中,服务器模式已经成为默认模式,尤其是在 64 位的操作系统上,这意味着即使你不显式指定
-server,JVM 通常也会自动按服务器模式的行为来运行。 - 客户端模式 (
-client) 在标准 JDK 中已被移除,但在某些嵌入式 JDK 或 Java ME 中可能仍然存在。 - 在大多数情况下,你不需要手动指定
-server,但显式指定可以确保你的应用在任何环境下都按照你期望的模式运行,是一种明确意图的好方法。
何时应该使用 -server?
强烈推荐使用 -server 的场景:
- 生产环境的应用程序:任何需要长时间、高并发、高吞吐量运行的服务。
- 后端服务:如 Web 服务器、微服务、API 网关等。
- 数据处理应用:如 Hadoop、Spark、Flink 等大数据框架。
- 应用服务器:如 Tomcat, JBoss, WebLogic 等。
可以考虑不使用 -server(或使用客户端模式)的场景:
- 桌面应用程序 (GUI):需要快速响应用户操作,启动延迟是关键。
- 自动化测试脚本:执行时间短,不需要长期的高性能。
- 开发调试:快速的编译和启动 cycle 能提高开发效率。
- 内存极其受限的环境:如嵌入式设备。
与其他性能参数的结合使用
-server 通常不是单独使用的,它需要与其他 JVM 参数配合,以达到最佳性能。
# 一个典型的生产环境启动脚本示例 java -server \ -Xms2g -Xmx2g \ # 设置堆的初始和最大大小为 2GB,防止堆动态调整带来的开销 -XX:+UseG1GC \ # 使用 G1 垃圾回收器(JDK 9+ 默认),它提供了更好的可预测性 -XX:MaxGCPauseMillis=200 \ # 尝试让 GC 暂停时间不超过 200ms -XX:+PrintGCDetails \ # 打印 GC 详细日志,用于监控 -XX:+PrintGCTimeStamps \ -jar my-application.jar
| 参数 | 核心思想 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
-server |
牺牲启动时间和内存,换取长期运行的峰值性能。 | 高吞吐量,充分利用多核 CPU,减少初期 GC。 | 启动慢,初始内存占用高,有预热期。 | 生产环境、后端服务、大数据处理。 |
-client |
牺牲长期性能,换取快速启动和低内存占用。 | 启动快,内存占用小。 | 长期运行性能差,无法充分利用多核。 | 桌面应用、测试、开发、嵌入式。 |
最终建议:
对于任何严肃的 Java 后端应用,都应该默认使用 -server 模式,并根据实际负载和硬件配置,结合 -Xms, -Xmx, -XX:+UseG1GC 等参数进行精细调优,在现代 JDK 中,虽然它可能是默认行为,但显式写出可以增强配置的可读性和意图的明确性。
