java 命令
无论在哪种 Shell 中,启动 Java 程序的核心都是 java 命令,它的基本语法如下:
java [选项] 类名 [参数]
[选项]: JVM 的启动参数,例如设置内存大小 (-Xmx)、垃圾回收器 (-XX:+UseG1GC) 等。类名: 你想要执行的 Java 主类的全限定名,com.example.MyApp。[参数]: 传递给 Java 程序main方法的参数。
第1步:最简单的启动方式
假设你已经:
- 安装了 Java 并配置好了
JAVA_HOME。 - 你的 Java 程序已经被编译成了
.class文件,或者打包成了.jar文件。
场景1:直接运行 .class 文件
-
编译 Java 源码:
# 假设你有一个 MyProgram.java 文件 javac MyProgram.java
这会生成一个
MyProgram.class文件。 -
运行编译后的文件:
# 运行当前目录下的 MyProgram.class java MyProgram
注意: 这里只写类名
MyProgram,不要带.class后缀。
场景2:运行 .jar 文件 (最常见的方式)
Java 程序通常被打包成 .jar (Java Archive) 文件以便分发。
-
创建 JAR 文件:
# 创建一个可执行的 JAR 文件,指定 Main-Class jar cvfe MyApp.jar com.example.MainClass com/example/*.class
c: 创建新的 JAR 文件。v: 生成详细输出。f: 指定 JAR 文件名。e: 指定入口点(主类)。
-
运行 JAR 文件:
# 使用 -jar 选项来运行 JAR 文件 java -jar MyApp.jar
如果你的 JAR 文件没有在
META-INF/MANIFEST.MF中正确配置Main-Class,你也可以通过以下方式指定:java -cp MyApp.jar com.example.MainClass
第2步:传递参数给 Java 程序
你的 Java 程序的 main 方法可以接收字符串数组参数,在 Shell 中,只需在类名或 JAR 文件名后跟上这些参数即可。
Java 代码示例 (ArgsDemo.java):
public class ArgsDemo {
public static void main(String[] args) {
System.out.println("程序接收到 " + args.length + " 个参数:");
for (int i = 0; i < args.length; i++) {
System.out.println("参数 " + (i + 1) + ": " + args[i]);
}
}
}
Shell 中运行并传参:
# 编译 javac ArgsDemo.java # 运行并传递三个参数 java ArgsDemo "Hello World" 123 --verbose
输出:
程序接收到 3 个参数:
参数 1: Hello World
参数 2: 123
参数 3: --verbose
对 JAR 文件传参:
java -jar MyApp.jar config.properties mode=production
第3步:设置类路径 (-cp 或 -classpath)
当你的 Java 程序依赖了第三方库(如 .jar 文件或 .class 文件)时,你需要使用 -cp (Classpath) 选项来告诉 JVM 去哪里查找这些依赖。
场景1:依赖当前目录下的其他 JAR
假设你的项目结构如下:
.
├── MyApp.jar
├── lib/
│ ├── library1.jar
│ └── library2.jar
└── ...
运行方式:
# 使用冒号 : 分隔多个路径(Linux/macOS) java -jar MyApp.jar -cp ./lib/library1.jar:./lib/library2.jar # 或者不使用 -jar,而是用 -cp 指定所有依赖 java -cp ".:./lib/library1.jar:./lib/library2.jar:MyApp.jar" com.example.MainClass
场景2:依赖系统路径下的库
如果你已经将库文件(如 mysql-connector-java.jar)放到了 /usr/local/lib/,可以这样使用:
java -cp "/usr/local/lib/mysql-connector-java.jar:." com.example.DatabaseApp
场景3:使用通配符 (Linux/macOS)
现代 Java 版本支持在类路径中使用通配符 来简化命令。
# * 会自动替换为 lib 目录下所有的 .jar 文件 java -jar MyApp.jar -cp "./lib/*"
注意: Windows 的命令提示符不支持 通配符,需要使用第三方工具如
ClasspathUtils或手动列出所有 JAR。
第4步:JVM 选项(内存、GC 等)
在生产环境中,为 Java 程序分配正确的内存至关重要,这些选项直接跟在 java 命令之后,类名或 -jar 之前。
常用选项示例:
# 设置最大堆内存为 2GB,初始堆内存为 512MB java -Xmx2g -Xms512m -jar my-big-app.jar # 使用 G1 垃圾回收器 java -XX:+UseG1GC -jar my-app.jar # 设置元空间大小 (Java 8+) java -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m -jar my-app.jar # 启用 JMX 以便使用 VisualVM 或 JConsole 监控 java -Dcom.sun.management.jmxremote.port=9001 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -jar my-app.jar
第5步:在 Shell 脚本中启动(生产环境实践)
在实际生产环境中,我们通常不会直接在命令行运行,而是编写一个 Shell 脚本,这样做的好处是:
- 可以方便地管理启动参数。
- 可以配置日志输出。
- 可以设置运行环境(如
JAVA_HOME)。 - 可以实现后台运行、日志轮转等功能。
示例 start_app.sh 脚本:
#!/bin/bash
# 1. 设置环境变量
# 强制使用特定版本的 Java
export JAVA_HOME=/opt/java/jdk-17
export PATH=$JAVA_HOME/bin:$PATH
# 2. 定义应用变量
APP_NAME="MyAwesomeApp"
APP_JAR="target/MyAwesomeApp-1.0.0.jar"
APP_LOG_FILE="logs/app.log"
APP_PID_FILE="logs/app.pid"
JAVA_OPTS="-Xms512m -Xmx2g -XX:+UseG1GC -Dspring.profiles.active=prod"
# 3. 检查 JAR 文件是否存在
if [ ! -f "$APP_JAR" ]; then
echo "错误: JAR 文件 $APP_JAR 不存在!"
exit 1
fi
# 4. (可选) 创建日志和PID文件目录
mkdir -p logs
# 5. 检查应用是否已经在运行
if [ -f "$APP_PID_FILE" ]; then
PID=$(cat "$APP_PID_FILE")
if ps -p $PID > /dev/null; then
echo "$APP_NAME 已经在运行,PID: $PID"
exit 1
else
echo "清理过期的 PID 文件: $APP_PID_FILE"
rm -f "$APP_PID_FILE"
fi
fi
# 6. 启动应用
echo "正在启动 $APP_NAME..."
# nohup 表示即使终端关闭,程序也会继续运行
# > $APP_LOG_FILE 2>&1 表示将标准输出和标准错误都重定向到日志文件
# & 表示在后台运行
nohup java $JAVA_OPTS -jar $APP_JAR > $APP_LOG_FILE 2>&1 &
# 7. 记录 PID
echo $! > $APP_PID_FILE
echo "$APP_NAME 启动成功,PID: $!,日志文件: $APP_LOG_FILE"
如何使用这个脚本:
- 保存为
start_app.sh。 - 赋予执行权限:
chmod +x start_app.sh。 - 运行脚本:
./start_app.sh。
配套的 stop_app.sh 脚本:
#!/bin/bash
APP_PID_FILE="logs/app.pid"
if [ -f "$APP_PID_FILE" ]; then
PID=$(cat "$APP_PID_FILE")
echo "正在停止 PID 为 $PID 的进程..."
kill $PID
# 等待进程优雅退出
for i in {1..10}; do
if ! ps -p $PID > /dev/null; then
echo "$APP_NAME 已停止。"
rm -f "$APP_PID_FILE"
exit 0
fi
sleep 1
done
# 如果超时,强制杀死
echo "超时,强制杀死进程..."
kill -9 $PID
rm -f "$APP_PID_FILE"
else
echo "$APP_PID_FILE 文件不存在,可能应用未运行。"
fi
常见问题与排查
-
'java' command not found- 原因: 系统没有找到
java命令。 - 解决: 确保 Java 已正确安装,
JAVA_HOME环境变量和PATH环境变量已正确配置。
- 原因: 系统没有找到
-
Error: Could not find or load main class com.example.MyApp- 原因:
- 类名写错了。
- 类所在的包目录结构不正确。
-cp(类路径) 没有包含.class文件所在的目录。- 在 Windows 上,路径分隔符是分号 而不是冒号 。
- 解决: 仔细检查类名和类路径,可以使用
echo $CLASSPATH(Linux/macOS) 或echo %CLASSPATH%(Windows) 查看当前类路径。
- 原因:
-
OutOfMemoryError: Java Heap Space- 原因: Java 堆内存不足。
- 解决: 增加 JVM 的最大堆内存,使用
-Xmx参数,-Xmx4g。
| 任务 | 命令示例 |
|---|---|
运行 .class |
java MyClass |
运行 .jar |
java -jar myapp.jar |
| 传参 | java MyClass arg1 arg2 或 java -jar myapp.jar arg1 arg2 |
| 设置类路径 | java -cp ".:lib/*" com.example.Main |
| 设置内存 | java -Xmx2g -Xms512m -jar myapp.jar |
| 后台运行 | nohup java -jar myapp.jar > app.log 2>&1 & |
掌握这些基本操作和脚本编写技巧,你就可以在 Shell 中灵活、稳定地管理和启动你的 Java 应用程序了。
