LoginSignup
0
0

More than 1 year has passed since last update.

[Docker][Java] Java プロセスのコンテナで jstat が採れない

Posted at

docker コンテナで動かしている Java プロセスの jstat を採る話。

以下のように実行してみると。。

$ docker exec -t --user 1000 {container-id} jstat -gc 1

こんなエラーになりました。

sun.jvmstat.monitor.MonitorException: 1 not found
        at jdk.internal.jvmstat/sun.jvmstat.perfdata.monitor.protocol.local.PerfDataBuffer.<init>(PerfDataBuffer.java:84)
        at jdk.internal.jvmstat/sun.jvmstat.perfdata.monitor.protocol.local.LocalMonitoredVm.<init>(LocalMonitoredVm.java:68)
        at jdk.internal.jvmstat/sun.jvmstat.perfdata.monitor.protocol.local.MonitoredHostProvider.getMonitoredVm(MonitoredHostProvider.java:77)
        at jdk.jcmd/sun.tools.jstat.Jstat.logSamples(Jstat.java:107)
        at jdk.jcmd/sun.tools.jstat.Jstat.main(Jstat.java:70)
Caused by: java.lang.IllegalArgumentException: Could not map vmid to user Name
        at java.base/jdk.internal.perf.Perf.attach(Native Method)
        at java.base/jdk.internal.perf.Perf.attachImpl(Perf.java:272)
        at java.base/jdk.internal.perf.Perf.attach(Perf.java:202)
        at jdk.internal.jvmstat/sun.jvmstat.perfdata.monitor.protocol.local.PerfDataBuffer.<init>(PerfDataBuffer.java:64)

PID 1 がないというのだけど、java プロセスは確かに PID=1 で動いてる。。?

エラーメッセージで調べてみると、以下のような記事が見つかった。

jdk6u23 で jps/jstat が動作しないあるある
https://tksmd.hatenablog.com/entry/20110119/p1

jps、jstat は /tmp/hsperfdata_{ユーザ名} というディレクトリを見て対象プロセスの情報を得るので、/tmp の部分がプロパティで変更されてるとうまく動かないというものでした。

試してみると、Java の調査コマンドで確かに jps、jstat が動きません。

  • × jps
  • × jstat -gc 1
  • jstack 1
  • jmap -histo:live 1
  • jcmd 1 GC.heap_info

ただし、記事にあるように /tmp の部分は変更されていません。

hsperfdata ディレクトリは Java プロセス起動時に作られるとあるのに、該当のディレクトリができていません。

どうやら、hsperfdata_{ユーザ名} とあるように、実行ユーザの UID に対するユーザがないと対象のディレクトリが作られないようですね。

docker 実行時に実行ユーザの UID だけ指定してユーザを切り替えていたのがダメだったようです。

$ docker exec -t --user 1000 {container-id} id
uid=1000 gid=0(root) groups=0(root)  ★UIDに対するユーザがいない

というわけで、Java コンテナの起動スクリプト(entrypoint.sh) 内で UID に対するユーザを作るようにしてみました。

entrypoint.sh
UID=${UID:-1000}
useradd -m -u ${UID} myuser

実行ユーザが設定できています。

$ docker exec -t --user 1000 {container-id} id
uid=1000(myuser) gid=0(root) groups=0(root)

hsperfdata ディレクトリも作られるようになりました。

$ docker exec -t --user 1000 {container-id} ls -1 /tmp
hsperfdata_myuser
  :

これで、無事 jstat が採れるようになりました。

$ docker exec -t --user 1000 {container-id} jstat -gc 1
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT
 0.0   5120.0  0.0   5120.0 74752.0  10240.0   431104.0   65111.7   75264.0 72714.0 10240.0 9118.1     35    3.934   0      0.000   8      0.397    4.331

// EOF

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0