在 CentOS 系统上启动 Java 应用程序是部署和维护 Java 服务的基础操作,根据应用类型和运行环境的不同,启动方式也多种多样,从简单的命令行执行到配置为系统服务,以满足开发和生产环境的不同需求,本文将详细介绍在 CentOS 上启动 Java 程序的多种方法,并涵盖相关的配置和最佳实践。

前提条件:验证 Java 环境
在启动任何 Java 应用之前,首要任务是确保系统已正确安装 Java 开发工具包(JDK)或 Java 运行时环境(JRE),并且环境变量配置无误。
打开终端,输入以下命令来检查 Java 版本:
java -version
如果安装成功,终端会显示类似如下的版本信息:
openjdk version "11.0.12" 2021-07-20
OpenJDK Runtime Environment (build 11.0.12+7)
OpenJDK 64-Bit Server VM (build 11.0.12+7, mixed mode, sharing)
检查 JAVA_HOME 环境变量是否设置,这对于许多 Java 应用和构建工具至关重要:
echo $JAVA_HOME
该命令应输出 JDK 的安装路径,/usr/lib/jvm/java-11-openjdk-11.0.12.0.7-0.el7_9.x86_64,如果此变量未设置,你需要将其添加到 /etc/profile 或用户的 .bash_profile 文件中。
直接运行 .class 文件
这是最基础的启动方式,适用于运行已编译的、不包含外部依赖的单一 .class 文件,命令格式为 java <包名>.<类名>。
假设你有一个编译好的类文件 MyApp.class,它位于 com/example 目录下,其完整包名为 com.example.MyApp,你需要在类文件的根目录(即 com 目录的上一级目录)执行以下命令:
java com.example.MyApp
如果程序需要接收命令行参数,可以直接在命令末尾追加:
java com.example.MyApp arg1 arg2
使用 java -jar 运行可执行 JAR 包
在现代 Java 开发中(如 Spring Boot 项目),将应用及其所有依赖打包成一个可执行的 JAR 文件是非常普遍的做法,启动这类应用非常简单。
使用 -jar 选项指定 JAR 文件路径即可:
java -jar /path/to/your/application.jar
在生产环境中,我们通常需要调整 JVM 的内存分配以提高性能和稳定性,常用的参数包括:

-Xms:设置 JVM 初始堆内存大小。-Xmx:设置 JVM 最大堆内存大小。
一个完整的启动命令示例:
java -Xms512m -Xmx1024m -jar /path/to/your/application.jar
这个命令为应用分配了 512MB 的初始内存和最大 1GB 的堆内存。
通过 -cp 指定 Classpath 运行
当你的项目依赖外部的 JAR 包时,需要使用 -cp(或 -classpath)参数来告诉 JVM 在哪里查找类文件和依赖库。
Classpath 中的多个路径用冒号 (Linux/macOS)分隔,假设你的项目结构如下:
my-project/
├── lib/
│ ├── dependency1.jar
│ └── dependency2.jar
└── com/
└── example/
└── MyApp.class
启动命令应该是:
java -cp "lib/*:." com.example.MyApp
这里的 lib/* 表示包含 lib 目录下的所有 JAR 文件, 表示当前目录,用于查找 com.example.MyApp 类。
生产环境:后台运行与系统服务
在服务器上,我们通常不希望 Java 应用随着终端会话的结束而终止,需要将其配置为在后台持续运行。
后台运行
使用 nohup 和 & 组合可以实现后台运行,即使你退出登录,程序也会继续执行。
nohup java -jar /path/to/your/application.jar > /dev/null 2>&1 &
nohup:让命令忽略挂起信号。&:将命令放到后台执行。> /dev/null 2>&1:将标准输出和标准错误重定向到/dev/null,即丢弃所有日志,避免产生nohup.out文件,在生产环境中,你可能会将日志重定向到指定文件,如> app.log 2>&1。
配置为 Systemd 服务(推荐)
在 CentOS 7 及更高版本中,使用 systemd 管理服务是最佳实践,它能提供开机自启、自动重启、日志管理等功能。
-
创建服务文件:
在
/etc/systemd/system/目录下创建一个服务文件,myapp.service。
sudo vim /etc/systemd/system/myapp.service
-
编写服务配置:
在文件中填入以下内容,请根据你的实际情况修改路径和用户。
[Unit] Description=My Java Application Service After=syslog.target network.target [Service] User=javauser Group=javauser ExecStart=/usr/lib/jvm/java-11-openjdk/bin/java -Xms512m -Xmx1024m -jar /opt/apps/myapp.jar SuccessExitStatus=143 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target
[Unit]:定义服务的元数据和依赖关系。[Service]:核心配置部分。User/Group:指定运行服务的用户和组,出于安全考虑,不建议使用root。ExecStart:启动服务的完整命令,建议使用 Java 可执行文件的绝对路径。Restart:定义服务退出后的重启策略,on-failure表示仅在非正常退出时重启。
[Install]:定义如何安装服务。
-
启用和启动服务:
# 重新加载 systemd 配置 sudo systemctl daemon-reload # 启动服务 sudo systemctl start myapp.service # 设置服务开机自启 sudo systemctl enable myapp.service # 查看服务状态 sudo systemctl status myapp.service
通过 systemd,你可以使用 systemctl stop myapp.service 停止服务,使用 journalctl -u myapp.service -f 查看实时日志,管理非常便捷。
启动方式对比
| 启动方式 | 使用场景 | 优点 | 缺点 |
|---|---|---|---|
java com.example.MyApp |
运行单个.class文件,测试阶段 |
简单直接 | 不方便管理依赖,不适合生产 |
java -jar app.jar |
运行可执行JAR包(如Spring Boot) | 方便,包含所有依赖 | 前台运行,会话结束即终止 |
nohup java ... & |
简单的后台运行需求 | 无需额外配置,快速部署 | 管理粗糙,缺乏自动重启、日志聚合等高级功能 |
Systemd |
生产环境、长期运行的服务 | 稳定可靠,支持开机自启、自动重启、统一日志管理 | 配置相对复杂,需要root权限 |
相关问答FAQs
我已经设置了 JAVA_HOME 环境变量,但在任何目录下运行 java 命令都提示“command not found”,这是为什么?
解答: 这个问题通常是因为 PATH 环境变量没有包含 Java 的可执行文件路径。JAVA_HOME 只是一个指向 Java 安装根目录的变量,系统需要通过 PATH 变量来查找 java、javac 等命令,你需要将 $JAVA_HOME/bin 目录添加到 PATH 中,可以编辑 /etc/profile 文件,在末尾添加以下两行:
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk # 请替换为你的实际路径 export PATH=$PATH:$JAVA_HOME/bin
保存后,执行 source /etc/profile 或重新登录终端,即可生效。
我的 Java 应用在启动时报错 “Permission denied” 或 “Address already in use”,该如何处理?
解答: 这两个问题很常见:
- “Permission denied”(权限被拒绝):
- 文件权限: 检查你的 JAR 包或启动脚本是否有执行权限,可以使用
chmod +x your-app.jar或chmod +x start.sh来添加执行权限。 - 端口权限: 如果你的应用需要绑定 1024 以下的端口(如 80 端口),普通用户是没有权限的,你需要使用
root用户启动,或者使用setcap命令给 Java 可执行文件授权(更安全的方式):sudo setcap cap_net_bind_service=+ep $(readlink -f $(which java))。
- 文件权限: 检查你的 JAR 包或启动脚本是否有执行权限,可以使用
- “Address already in use”(地址已被使用):
- 这表示你要监听的端口已经被另一个进程占用了,你可以使用
netstat -tulpn | grep <端口号>或ss -tulpn | grep <端口号>来查找占用该端口的进程。 - 找到进程 ID(PID)后,可以使用
kill -9 <PID>来终止该进程,然后重新启动你的 Java 应用,如果占用的进程是重要的系统服务,则需要为你的 Java 应用配置一个不同的端口。
- 这表示你要监听的端口已经被另一个进程占用了,你可以使用