必知必會Java命令-jps

劍舞星魂發表於2023-12-10

你好,我是阿光。

最近想著把工作中使用過的java命令都梳理一下,方便日後查閱。雖然這類文章很多,但自己梳理總結後,還是會有一些新的收穫。這也是這篇筆記的由來。

今天先聊聊 jps 命令。

命令概述⭐

jps命令是JDK提供的一個工具,用於檢視目標系統上的Java程式基本資訊(程式ID, 啟動類,啟動引數等)。命令在JDK安裝目錄的bin目錄下,比如在我的window下D:\Java\jdk1.8.0\bin\jps.exe。但JRE沒有提供這個命令。不過從Java9模組化開始,已經不區分JDK和JRE了。

這個命令只會檢測到目標系統上HotSpot版本的,具有訪問許可權的JVM資訊。

命令的官方文件可檢視這個地址The jps Command (oracle.com)

命令用法⛵

我的演示環境是在window11, jdk17版本下

我們可以透過jps -h 或者 jps --help 或者 jps -help檢視這個命令的基本用法:

jps --help
usage: jps [--help]
       jps [-q] [-mlvV] [<hostid>]

Definitions:
    <hostid>:      <hostname>[:<port>]
    -? -h --help -help: Print this help message and exit.

中括號裡的選項都是可選的,最簡單的就是jps

jps
35936 Jps
1076  RemoteMavenServer36

這裡沒有指定主機,所以只會查詢本地主機上的JVM。第一列是程式ID,第二列是啟動類名。可以看到,jps命令本身也是一個Java程式,它的啟動類是Jps。

-q選項會讓命令只輸出程式ID,如下:

jps -q
35936
1076

-mlvV選項可以任意指定一個,也可以同時指定多個,它們可以隨意組合。

  • -m 選項會顯示傳遞給main方法的引數,即程式自定義的一些引數。
  • -l 選項會顯示啟動類的完整包名稱或者啟動JAR的完整路徑名。
  • -v 選項會顯示傳遞給虛擬機器的引數,比如-Dxxx=v形式指定的引數,-Xms128M引數等。
  • -V 大V選項只會輸出PID和類名,jpsjps -V的輸出是一樣的。

這裡我本地執行了一個Java程式,啟動類是Main,並且指定了一些自定義的引數.

  1. 列出main方法引數:jps -m
jps -m
16596 Main test=11 測試引數:a
18796 Jps -m
  1. 列出啟動類全名:jps -l
jps -l
16596 com.ggy.softman.Main
11836 jdk.jcmd/sun.tools.jps.Jps
  1. 列出虛擬機器引數:jps -v
jps -v
29716 Main -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8
11388 Jps -Dapplication.home=D:\Java\jdk-17.0.6.10 -Xms8m -Djdk.module.main=jdk.jcmd
  1. 組合命令,輸出資訊更豐富:jps -lmv
jps -lmv
31948 com.ggy.softman.Main test=11 測試引數:a -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8
29008 jdk.jcmd/sun.tools.jps.Jps -lmv -Dapplication.home=D:\Java\jdk-17.0.6.10 -Xms8m -Djdk.module.main=jdk.jcmd

該命令也可以顯示遠端主機的Java程式資訊,只要在命令的最後帶上hostid。這種情況基本使用很少,這裡也沒演示了,可以檢視官網文件。

連線遠端主機時,遠端主機上必須執行jstatd命令。

使用場景🌳

這裡我總結了一下日常開發中,使用到該命令的場景。

  1. 有時候需要登入到伺服器上排查一些問題,檢視服務日誌,但不太清楚程式部署在哪個目錄下,這時候我會透過jps -lv | grep xxx 查詢指定名的程式,一般在輸出裡會顯示一些目錄資訊。
  2. 快速檢視Java服務是否正常,PID是什麼,然後結合其他命令使用。
  3. 有些情況下,快速檢視下Java服務的引數是否配置正確。

常見問題❓

這裡我總結了一下該命令經常會遇到的一些問題。

  1. command not found

出現這個報錯,一般有兩種情況,一是沒有配置好JAVA_HOME環境變數,二是安裝的是JRE,沒有帶jps命令。

還有種情況是使用的JDK版本低於1.5。

  1. 命令執行後沒有任何輸出,或者ps命令顯示有Java程式,但jps命令沒有顯示該程式。

出現這種情況,可以按以下步驟排查:

a. Java服務和jps命令是否是在同一個使用者下執行的;

b. {tmpdir}/hsperfdata_{user_name}/目錄下是否有檔案。tmpdir是系統臨時目錄。

window一般是: C:\Users\user_name\AppData\Local\Temp\

linux一般是: /tmp

如果當前使用者沒有該臨時目錄的讀取許可權,jps命令也會失效。

有時候linux系統會定時清理臨時目錄,也會導致該目錄為空。

jps命令其實是用Java實現的,原理就是透過掃描{tmpdir}/hsperfdata_{user_name}/目錄下的程式檔案。每個Java程式啟動時,都會在該目錄下生成一個以PID命名的檔案。下面是我window下的:

每個程式檔案裡都記錄了該虛擬機器程式的很多資訊。基本上很多Java命令都是從這個檔案裡獲取一些資訊的。下面是檔案的部分內容:

很多Java命令都可以看到原始碼,Java1.8及以下版本是在lib/tools.jar裡,1.8以上版本移到了多個模組下,jps、jstack、jinfo等基本命令是在jmods/jdk.jcmd.jmod裡,還有一些是在獨立的模組下,比如jdk.jlink.jmod。

有時遇到一些奇怪的異常時,可以使用 jps -J-Djps.debug=true -J-Djps.printStackTrace=true命令,可以獲取到jps命令的詳細錯誤資訊。

jps命令就是這些了,下次jstack再見。

參考資料ℹ️

  1. The jps Command (oracle.com)

相關文章