※当サイトの記事には、広告・プロモーションが含まれます。

lvmidとpidがややこしいがjavaコマンドとjstatコマンドをワンライナーで実行したい

www.itmedia.co.jp

www.itmedia.co.jp

⇧ 画像生成AI部門とか作って棲み分けしたら良いんじゃないかね。

Javaのlvmidとは?

見つけ辛いんですが、

docs.oracle.com

⇧ 上記の中の jpsコマンドのリンクを押下して遷移したページの説明によると、

docs.oracle.com

jpsコマンドは、ターゲット・システムで計測された各JVMについて、ローカルJVM識別子、つまりlvmidをレポートします。 lvmidは、一般的にはJVMプロセスに対するオペレーティング・システムのプロセス識別子ですが、必ずしもそうであるとは限りません。 オプションを指定しない場合、jpsコマンドは、各Javaアプリケーションのlvmidのあとに、アプリケーションのクラス名またはjarファイル名の短い形式を一覧表示します。 この簡単な形式のクラス名とJARファイル名では、クラスのパッケージ情報またはJARファイル・パス情報が省略されています。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jps.html

⇧ う~む、「local virtual machine identifier」の略とかなんかな?

ノート:

将来のリリースで形式が変更される可能性があるため、jps出力を解析するスクリプトを作成しないことをお薦めします。 jpsの出力を解析するスクリプトを作成する場合は、このツールの将来のリリースにより、そのスクリプトを変更する必要があることに留意してください。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jps.html

⇧ 非推奨とするなら、代替案を出して欲しいところですな...

Javaのpidとは?

これまた、見つけ辛いんだが、

docs.oracle.com

pid
出力されるスタック・トレースのプロセスIDです。 プロセスはJavaプロセスである必要があります。 マシンで実行されているJavaプロセスのリストを取得するには、psコマンドを使用するか、またはJVMプロセスが別のdockerインスタンスで実行されていない場合はjpsコマンドを使用します。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstack.html

⇧ jstackコマンドの説明にpidについての記載があり、何やら、pidを取得するには、

  • psコマンド
  • jpsコマンド

のどちらかを使うとなっており、jpsコマンドで取得できるのは、「ローカルJVM識別子(lvmid:local virtual machine identifier)」であるからして、

  • ローカルJVM識別子(lvmid:local virtual machine identifier)
  • プロセス識別子(pid:process identifier)

が同じになるケースがあるということになるっぽい...、分かり辛過ぎるんだが...。

そして、jpsコマンドと同じく、

ノート:

このコマンドはサポートされておらず、JDKの将来のリリースでは使用できない可能性があります。 dbgeng.dllファイルが存在しないWindowsシステムでは、これらのツールが機能するように、Windows用のデバッグ・ツールをインストールする必要があります。 PATH環境変数には、ターゲット・プロセスで使用されるjvm.dllのロケーション、またはコア・ダンプ・ファイルの生成元のロケーションが含まれている必要があります。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstack.html

⇧ お前もか...

javaコマンドとは

Oracleのドキュメントによりますと、

docs.oracle.com

javaコマンドはJavaアプリケーションを起動します。 それには、Java Virtual Machine (JVM)を起動し、指定されたクラスをロードして、そのクラスmain()メソッドを呼び出します。 このメソッドは、publicおよびstaticを宣言する必要があり、値を返すことはできません。また、パラメータとしてString配列を受け入れる必要があります。 メソッド宣言の形式は次のとおりです。

public static void main(String[] args)

https://docs.oracle.com/javase/jp/17/docs/specs/man/java.html

ソース・ファイル・モードでは、javaコマンドはソース・ファイルで宣言されたクラスを起動できます。 ソース・ファイル・モードの使用方法の詳細は、「ソース・ファイル・モードで単一ファイルのソース・コードのプログラムを起動する方法」を参照してください。

https://docs.oracle.com/javase/jp/17/docs/specs/man/java.html

ソース・ファイル・モードでの実行の手順:
  • 実行されるクラスは、ソース・ファイル内で最初に検出された最上位クラスです。 標準のpublic static void main(String[])メソッドの宣言が含まれている必要があります。

https://docs.oracle.com/javase/jp/17/docs/specs/man/java.html

⇧ 2種類の実行方法があるらしいのですが、どちらにしろ、

public static void main(String[] args)

⇧ mainメソッドが必要らしい。

mainメソッドについては、Java 21から、

qiita.com

⇧ 書き方を変えることができるみたい。

jstatコマンドとは?

Oracleのドキュメントによりますと、

docs.oracle.com

jstatコマンドは、設置されているJava HotSpot VMのパフォーマンス統計情報を表示します。 ターゲットJVMは、仮想マシン識別子またはvmidオプションによって識別されます。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstat.html

jstatコマンドでは、一般オプションと出力オプションの2つのタイプのオプションがサポートされています。 一般オプションを使用した場合、jstatコマンドは簡単な使用率およびバージョン情報を表示します。 出力オプションでは、統計データ出力の内容と形式を指定します。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstat.html

すべてのオプションとその機能は、将来のリリースで変更または廃止される可能性があります。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstat.html

⇧ とあり、「Java 仮想マシンJVMJava Virtual Machine)」のパフォーマンス統計情報が取得できるらしい。

で、お約束の、

ノート:

jstatコマンドの出力を解析するためのスクリプトは記述しないでください。そのようなフォーマットは、将来のリリースでは変更される可能性があるためです。 jstatコマンド出力を解析するスクリプトを記述する場合は、このツールの今後のリリースで変更される予定です。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstat.html

⇧ お前もか...

Javaのpidと「Java 仮想マシンJVMJava Virtual Machine)」

OpenJDKの「HotSpot」のRuntimeの説明によると、

VM Lifecycle

The following sections gives an overview of the general purpose java launcher pertaining to the lifecyle of the HotSpot VM.

Launcher

There are several HotSpot VM launchers in the Java Standard Edition, the general purpose launcher typically used is the java command on Unix and on Windows java and javaw commands, not to be confused with javaws which is a network based launcher.

The launcher operations pertaining to VM startup are:

  1. Parse the command line options, some of the command line options are consumed by the launcher itself, for example -client or -server is used to determine and load the appropriate VM library, others are passed to the VM using JavaVMInitArgs.
  2. Establish the heap sizes and the compiler type (client or server) if these options are not explicitly specified on the command line.
  3. Establishes the environment variables such as LD_LIBRARY_PATH and CLASSPATH.
  4. If the java Main-Class is not specified on the command line it fetches the Main-Class name from the JAR's manifest.
  5. Creates the VM using JNI_CreateJavaVM in a newly created thread (non primordial thread). Note: creating the VM in the primordial thread greatly reduces the ability to customize the VM, for example the stack size on Windows, and many other limitations
  6. Once the VM is created and initialized, the Main-Class is loaded, and the launcher gets the main method's attributes from the Main-Class.
  7. The java main method is then invoked in the VM using CallStaticVoidMethod, using the marshalled arguments from the command line.
  8. Once the java main method completes, its very important to check and clear any pending exceptions that may have occurred and also pass back the exit status, the exception is cleared by calling ExceptionOccurred, the return value of this method is 0 if successful, any other value otherwise, this value is passed back to the calling process.
  9. The main thread is detached using DetachCurrentThread, by doing so we decrement the thread count so the DestroyJavaVM can be called safely, also to ensure that the thread is not performing operations in the vm and that there are no active java frames on its stack.

https://openjdk.org/groups/hotspot/docs/RuntimeOverview.html

⇧「Java 仮想マシンJVMJava Virtual Machine)」は、起動する度にインスタンスが生成されて、mainメソッドの処理が完了する度に削除されるらしい、たぶん。

Wikipediaさんによると、

HotSpot, released as Java HotSpot Performance Engine, is a Java virtual machine for desktop and server computers, developed by Sun Microsystems and now maintained and distributed by Oracle Corporation. It features improved performance via methods such as just-in-time compilation and adaptive optimization.

https://en.wikipedia.org/wiki/HotSpot_(virtual_machine)

⇧「Java 仮想マシンJVMJava Virtual Machine)」の一種と言えるのかしらね。

話を戻すと、javaコマンドは『javaコマンドはJavaアプリケーションを起動します。 それには、Java Virtual Machine (JVM)を起動し、指定されたクラスをロードして、そのクラスmain()メソッドを呼び出します。』とあるので、「Java 仮想マシンJVMJava Virtual Machine)」のインスタンスが生成されて、mainメソッドの処理が終了するとインスタンスが削除されますと、たぶん。

Java 仮想マシンJVMJava Virtual Machine)」のインスタンスが複数あったとしても、『lvmidは、一般的にはJVMプロセスに対するオペレーティング・システムのプロセス識別子ですが、必ずしもそうであるとは限りません。』で識別されますと、たぶん。

で、

  • ローカルJVM識別子(lvmid:local virtual machine identifier)
  • プロセス識別子(pid:process identifier)

は同じものとして扱えることもあると考えられるとありましたと。

ということは、「Java 仮想マシンJVMJava Virtual Machine)」のインスタンスが削除されたら、pid(Javaプロセス)も終了するってことなんかね?

つまり、mainメソッドの処理が終了したら、pid(Javaプロセス)も消えるのか?

lvmidとpidがややこしいがjavaコマンドとjstatコマンドをワンライナーで実行したい

う~む、相変わらず、Javaのプロセスのライフサイクルがよく分からんのだが、仮に、mainメソッドの処理が終了すると、Javaのプロセスも終了するとした場合、困ったことが出てきますと。

それが何かと言うと、jstatコマンドのドキュメントを見ると、

jstat outputOptions [-t] [-h linesvmid [interval [count]]

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstat.html

vmid
仮想マシン識別子。ターゲットのJVMを示す文字列です。 仮想マシン識別子」を参照してください。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstat.html

⇧ とあり、「vmid」の説明で「仮想マシン識別子」を参照とあり、

仮想マシン識別子

vmid文字列の構文は、URIの構文に対応しています。

[protocol:][//]lvmid[@hostname[:port][/servername]

vmid文字列の構文は、URIの構文に対応しています。 vmid文字列は、ローカルJVMを表す単純な整数から、通信プロトコル、ポート番号、およびその他の実装固有の値を指定する複雑な構造まで様々に異なります。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstat.html#virtual-machine-identifier

lvmid
ターゲットJVMのローカル仮想マシン識別子です。 lvmidは、システム上のJVMを一意に識別するプラットフォーム固有の値です。 lvmidは、仮想マシン識別子の唯一の必須要素です。

https://docs.oracle.com/javase/jp/17/docs/specs/man/jstat.html#virtual-machine-identifier

⇧ と、ここで、「ローカルJVM識別子(lvmid:local virtual machine identifier)」が出てきますと。vmidが必須かどうか分からんので、何とも言えんのだけど、lvmidは必須らしい。

で、話を戻すと、アプリケーションサーバーのTomcatなどで稼働しているようなJavaのプログラムは、mainメソッドが終了することが無いので、「pid(Javaのプロセス)」も終了することが無いと思うのだけど、javaコマンドで実行するようなJavaのプログラムは、mainメソッドの中で無限ループでもしていない限り処理が終了するので、「pid(Javaのプロセス)」も終了してしまいますと、たぶん...。

前置きが長くなりましたが、表題の『lvmidとpidがややこしいがjavaコマンドとjstatコマンドをワンライナーで実行したい』という話にたどり着くわけですと。

で、Microsoft Bingに聞いてみたところ、以下のようなコマンドを提案されたんだけど、ちょっと時間が無くて動作確認はできてません...。

java [実行したいクラスファイル名、または、jarファイル名] & jps -lm | grep [実行したいクラスファイル名、または、jarファイル名] | awk '{print $1}' | xargs -I{} jstat -gcutil {}

まぁ、Javaのプロセスのライフサイクルがいまいちハッキリせんので、ワンライナーで実行とか不要かもしらんけど...

とりあえず、時間のある時に、本当にワンライナーの実行が可能なのかとか検証せねばですかね...

2023年9月30日(土)追記:↓ ここから

一応、以下でワンライナーっぽいの試してみました。シェルスクリプトに詳しくないので、正解かどうか分からないですが、それでも善き哉という方はご照覧くださいませ。

ts0818.hatenablog.com

2023年9月30日(土)追記:↑ ここまで

毎度モヤモヤ感が半端ない...

今回はこのへんで。