在 Linux 服务器上部署 Java 应用,核心就两步:装 JDK 和 配环境。虽然听起来简单,但坑不少。作为经常跟服务器打交道的老手,我直接给你一套最稳妥、最通用的实操方案。
目前主流的生产环境(尤其是国内云厂商如阿里云、腾讯云、华为云的 ECS/CVM)大多基于 CentOS 7/8、Ubuntu 18.04/20.04 或 Debian 系统。下面以最常见的 CentOS/RHEL 系列为例,兼顾 Ubuntu 的差异点。
第一步:选择并安装 JDK
这里有两个流派:包管理器安装(适合快速上手、依赖管理简单的场景)和 手动解压安装(适合生产环境、版本控制严格、需要自定义路径的场景)。
方案 A:使用包管理器安装(推荐用于开发测试或简单服务)
这是最快的方式,自动处理环境变量。
CentOS/RHEL:
# 查看可用的 OpenJDK 版本
yum list available | grep java-11-openjdk
# 安装 OpenJDK 11(目前 LTS 主力版本,Java 8 也可选)
sudo yum install java-11-openjdk-devel -y
# 验证安装
java -version
Ubuntu/Debian:
sudo apt update
sudo apt install openjdk-11-jdk -y
java -version
注意:
openjdk默认通常只包含 JRE(运行时),如果编译代码还需要jre-headless或jdk包。生产环境建议用jdk完整包。
方案 B:手动下载二进制包安装(生产环境推荐)
这种方式更可控,不依赖系统包管理器,方便多版本共存和管理。
-
下载 JDK
去 Oracle 官网或 Adoptium (Eclipse Temurin) 下载对应版本的.tar.gz文件。比如jdk-11.0.16_linux-x64_bin.tar.gz。 -
上传并解压
# 创建目录 sudo mkdir -p /usr/local/java # 假设你把 jdk 压缩包放在了 /tmp/jdk.tar.gz sudo tar -zxvf /tmp/jdk.tar.gz -C /usr/local/java/ # 重命名以便管理(可选) sudo mv /usr/local/java/jdk-11.0.16 /usr/local/java/jdk11 -
配置环境变量
编辑/etc/profile或在/etc/profile.d/下新建一个脚本(推荐后者,便于维护):sudo vi /etc/profile.d/java.sh写入以下内容(根据实际路径调整):
export JAVA_HOME=/usr/local/java/jdk11 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar -
生效配置
source /etc/profile -
验证
java -version javac -version # 确认编译器也正常 echo $JAVA_HOME # 检查变量是否加载
第二步:启动 Java 应用
装好 JDK 后,启动应用本身并不复杂,但有几个关键点需要注意,避免“能跑但容易挂”的情况。
1. 基础启动命令
假设你的应用是 myapp.jar,放在 /opt/apps/myapp/ 目录下。
cd /opt/apps/myapp/
java -jar myapp.jar
问题:这样启动后,终端关闭进程就死了。你需要后台运行。
2. 后台运行(三种常见方式)
方式一:nohup + & (最简单,适合临时调试或小流量服务)
nohup java -jar myapp.jar > app.log 2>&1 &
nohup:忽略挂起信号,终端关闭后继续运行。> app.log 2>&1:将标准输出和错误输出重定向到日志文件。&:放到后台执行。
缺点:无法优雅停止,PID 不好找,日志会无限增长。
方式二:systemd 服务(生产环境标准做法,强烈推荐)
Linux 原生支持 systemd,用它管理服务比 shell 脚本靠谱得多。
-
创建服务文件
sudo vi /etc/systemd/system/myapp.service -
写入配置
[Unit] Description=My Java Application After=network.target [Service] Type=simple User=root WorkingDirectory=/opt/apps/myapp/ ExecStart=/usr/local/java/jdk11/bin/java -Xms512m -Xmx1g -jar myapp.jar Restart=on-failure RestartSec=10 # 可选:限制资源 # LimitNOFILE=65535 [Install] WantedBy=multi-user.target-Xms512m -Xmx1g:务必设置堆内存大小,否则 JVM 会根据服务器负载动态调整,可能导致 OOM 或性能抖动。Restart=on-failure:崩溃后自动重启。
-
启用并启动服务
sudo systemctl daemon-reload sudo systemctl enable myapp.service sudo systemctl start myapp.service -
查看状态和日志
systemctl status myapp.service journalctl -u myapp.service -f # 实时查看日志
方式三:Docker 容器化(现代云原生首选)
如果你用的是云服务器,强烈建议考虑 Docker。它解决了“在我机器上能跑”的环境不一致问题。
FROM eclipse-temurin:11-jre
COPY myapp.jar /app.jar
ENTRYPOINT ["java", "-Xms512m", "-Xmx1g", "-jar", "/app.jar"]
构建镜像后:
docker run -d --name myapp -p 8080:8080 myapp-image
第三步:关键优化与避坑指南
-
时区问题
Java 应用默认可能使用 UTC 时间,导致日志时间和北京时间差 8 小时。
解决:启动参数加-Duser.timezone=GMT+8java -Duser.timezone=GMT+8 -jar myapp.jar -
内存溢出(OOM)
云服务器内存有限,不要给 JVM 分配太多。一般原则:-Xmx不超过物理内存的 50%-70%。- 如果是 Spring Boot 应用,注意内置 Tomcat 的内存占用,适当调小
-Xmx。 - 开启 GC 日志排查问题:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/gc.log
-
防火墙与安全组
很多新手配好了 Java 应用,发现网络访问不了。- 检查端口监听:
netstat -tuln | grep 8080或ss -tuln - 检查 Linux 防火墙:
firewall-cmd --zone=public --add-port=8080/tcp --permanent && firewall-cmd --reload - 检查云厂商安全组:阿里云/腾讯云的 ECS 控制台里,必须放行入方向 8080 端口!这是最常见的“玄学”故障。
- 检查端口监听:
-
中文乱码
如果应用涉及中文显示或日志打印乱码,确保系统 locale 正确:localectl set-locale LANG=en_US.UTF-8 # 或者 localectl set-locale LANG=zh_CN.UTF-8并在启动参数中强制指定编码:
-Dfile.encoding=UTF-8
总结
- 开发/测试:直接用
yum/apt装 OpenJDK,nohup启动。 - 生产环境:手动安装 JDK 到
/usr/local/java,用systemd管理进程,设置合理的-Xmx和时区参数。 - 云原生趋势:新项目优先考虑 Docker 部署,运维成本更低,迁移更方便。
按照这个流程走,基本不会出大问题。如果遇到具体报错,贴出 java -version 和启动时的异常栈,再针对性分析。
CLOUD云枢