前の記事で Java プロセスの docker コンテナの jstat が採れない問題を修正したら、今まで動いていた jmap/jstack が採れなくなった。。
[Docker][Java] Java プロセスのコンテナで jstat が採れない
https://qiita.com/batatch/items/a5d76b420702cc6322b5
以下のようなエラーになり、jmap/jstack の結果がアタッチ対象の Java プロセスの標準出力に出てしまう。
Exception in thread "main" com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file /proc/1/root/tmp/.java_pid1: target process 1 doesn't respond within 10500ms or HotSpot VM not loaded
at jdk.attach/sun.tools.attach.VirtualMachineImpl.<init>(VirtualMachineImpl.java:100)
at jdk.attach/sun.tools.attach.AttachProviderImpl.attachVirtualMachine(AttachProviderImpl.java:58)
at jdk.attach/com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:207)
at jdk.jcmd/sun.tools.jmap.JMap.executeCommandForPid(JMap.java:128)
at jdk.jcmd/sun.tools.jmap.JMap.histo(JMap.java:174)
at jdk.jcmd/sun.tools.jmap.JMap.main(JMap.java:112)
対象の Java プロセスも、jmap/jstack もユーザID を変更して実行しているのに、エラーメッセージにあるソケットファイル名は /proc/1/root/tmp/.java_pid1
と root ユーザとなっているので、root として jcmd を実行してみてもダメでした。
$ docker exec -t --user 1000 {container-id} jstack 1 #=> NG
$ docker exec -t {container-id} jstack 1 #=> NG
コンテナにシェルで入り、直接上記のファイルを見ようとしてもファイルへのアクセスができない。
root でもアクセスできないとは。。
そもそも、ユーザID を変更して実行しているのにソケットファイル名が root になってるのがおかしいようです。
結局、原因は対象の Java プロセスが entrypoint 内でユーザID を変えて java プロセスを実行していたからのようです。
コンテナ(PID=1) 自体が root で起動しているからソケットファイル名が root なのだと思われます。
chroot --userspec=1000:0 / java -ea ...
なので、jmap/jstack も同じように chroot して実行する必要がありました。
$ docker exec -t {container-id} bash -c "chroot --userspec=1000:0 / jstack 1"
これで jmap/jstack も採れるようになりました。
// EOF