jps -lvm 是查看Java进程主类、JAR路径及启动参数最直接的方式:-l输出完整类名或JAR路径,-m显示main方法参数,-v显示JVM参数,三者分两行呈现,覆盖启动核心要素。

用 jps -lvm 看主类、jar路径和启动参数
最直接的方式是组合使用 jps 的三个参数:-l(完整类名或 jar 路径)、-v(JVM 启动参数)、-m(main 方法参数)。这三者合起来,基本覆盖了“完整启动命令”的核心要素。
-
jps -l能区分/opt/app/my-service.jar和com.example.Main,避免只看类名Main无法定位服务的问题 -
jps -m会显示类似--spring.profiles.active=prod这类传给应用的参数,但不包括 JVM 参数 -
jps -v才真正输出-Xms512m -Xmx2g -Dfile.encoding=UTF-8这类关键配置,缺它容易误判内存或编码问题
所以实际执行:jps -lvm
输出示例:
12345 /opt/app/report-service.jar --server.port=8081 12345 /opt/app/report-service.jar -Xms1g -Xmx2g -Dspring.config.location=/etc/report/conf/
注意:这里第一行是 -m 输出,第二行是 -v 输出,jps 会把它们分两行打印,不是拼接成一条命令——它不还原 shell 命令格式,只是拆解呈现。
用 ps -f -p 查看原始命令行(含 java 可执行路径)
当需要确认 Java 是从哪个路径调起的(比如是否用了容器内嵌 JDK、是否被 wrapper 脚本封装),ps 更可靠。它展示的是进程创建时的完整 argv[0] 到 argv[n]。
-
ps -f -p 12345比ps -ef | grep java更精准,避免匹配到其他含 “java” 字符串的进程 - 输出中
CMD列会包含类似/usr/lib/jvm/java-17-openjdk-amd64/bin/java -jar /opt/app/api.jar --port=9000的完整行,这才是你真正执行的那条命令 - 如果看到
java被包装在sh -c '...'或bash /opt/app/start.sh里,说明启动逻辑不在jps覆盖范围内,得去查脚本
特别注意:ps 显示的命令长度受内核限制(通常是 4096 字节),超长参数会被截断,此时末尾可能看到 ... (truncated)。
jinfo -sysprops 补充环境变量级配置
有些启动参数(如 spring.config.location)虽在 jps -v 里,但系统级属性(如 user.timezone=Asia/Shanghai、java.io.tmpdir)未必显式出现在命令行中,而是由 jvm 自动注入或通过 -D 外部传入。这时 jinfo 就能补全上下文。
-
jinfo -sysprops 12345输出所有系统属性,可快速验证时区、编码、临时目录是否符合预期 - 若发现
user.home指向/root而非应用用户家目录,可能意味着服务以 root 启动,存在权限隐患 -
jinfo对 JDK 8+ 生效,但部分安全加固过的 JVM(如某些容器镜像)可能禁用该命令,报错Could not attach to process
为什么不用 cat /proc//cmdline ?
虽然 /proc/ 是 Linux 下最底层的命令行来源,但它用 \0 分隔参数,可读性差,且需手动替换不可见字符。更关键的是:
- Java 进程启动后,
cmdline不会随System.setProperty()动态更新,而jinfo -sysprops可反映运行时真实值 - 某些 JVM(如 Zing、GraalVM native image)不完全兼容
/proc/pid/cmdline格式,可能返回空或乱码 - 容器环境下(如 Docker),
/proc显示的是容器内视角,若未挂载procfs或使用hostPID: true,宿主机上直接读取会失败
所以除非调试内核级问题或写自动化脚本解析,否则没必要绕过 jps 和 ps 去碰 /proc。











