70856


サーバ内(CentOS)で動いてるJavaVMの起動コマンドを取得する為、jcmdをVM.command_lineオプションを付けて下記のように(1分に1回継続的に)実行しています。

[code]

    jcmd {プロセスID} VM.command_line
    
[/code]

これが時間経過で下記のエラーが返ってくるようになります。

[code]

    com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not responding or HotSpot VM not loaded
            at sun.tools.attach.LinuxVirtualMachine.<init>(LinuxVirtualMachine.java:106)
            at sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:63)
            at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208)
            at sun.tools.jcmd.JCmd.executeCommandForPid(JCmd.java:147)
            at sun.tools.jcmd.JCmd.main(JCmd.java:131)
    
[/code]

時間経過はJavaVMで動作しているアプリ内容によってまちまちですが、10日間でエラーが発生するようになる環境もあれば、27日間でエラーが発生するようになる環境もあります。

エラー内容を元に調査すると、以下のページが見つかりました。

[jstack / jmap コマンドを実行した際に "Unable to open socket file"
というメッセージが表示されスレッドダンプ/ヒープダンプが生成できません - Red Hat Customer
Portal](https://access.redhat.com/ja/solutions/915983)

上記ページの記述によれば、JavaVMの起動ユーザとは異なるユーザで実行した場合に発生するエラーとなっていますが、今回の事象は時間が経過する前後で実行ユーザは変えておらず、時間経過でエラーが発生する事から原因が特定できておりません。  
取得対象のJavaプロセスを再起動すると上記エラーは発生せず、しばらく(10日間ほど)すると再度エラーが発生するようになります。

原因が特定できず、困窮しております。


CC BY-SA 4.0
2020-10-01T06:31:41.587
70855
2020-10-02T11:33:56.390
2020-10-02T11:33:56.390
3060
31179
question
java centos java8
jcmdのVM.command_lineオプションが時間経過で使用できなくなる


ぱっと見の回答ですが、Javaのpidファイルが`/tmp`配下などの定期的に削除されるディレクトリーに出力されるようになっていて、それが10日間や27日間で削除されることでこの問題が起きていないですかね？

【回答追記】

このエラーが出るのは、`LinuxVirtualMachine.findSocketFile(int)`がnullを返す時で、このメソッドは/proc/[プロセスID]/cwd/
か /tmp 配下の .java_pid[プロセスID]
という名前のファイルの存在をチェックしています。何らかの理由でこのファイルが無いか、権限などの理由で読み込めないはずですね。

[code]

    // Return the socket file for the given process.
    // Checks working directory of process for .java_pid<pid>. If not
    // found it looks in temp directory.
    private String findSocketFile(int pid) {
        // First check for a .java_pid<pid> file in the working directory
        // of the target process
        String fn = ".java_pid" + pid;
        String path = "/proc/" + pid + "/cwd/" + fn;
        File f = new File(path);
        if (!f.exists()) {
            // Not found, so try temp directory
            f = new File(tmpdir, fn);
            path = f.exists() ? f.getPath() : null;
        }
        return path;
    }
    
[/code]


CC BY-SA 4.0
2020-10-01T07:07:01.900
70856
2020-10-02T06:07:21.290
2020-10-02T06:07:21.290
21092
21092
70855
answer


RHELかCentOS環境と想定しての回答です。  
`jcmd`等の要求を受け付けるためのソケットファイルが(daily cronで実行される)`tmpwatch`で削除されていると予想します。  
(`tmpwatch`は指定のディレクトリにある、一定期間アクセスのないファイルを削除するスクリプトです)

毎日`jcmd`で何かしらアクセスし続けるようcronでスクリプトを記述すると、事象解消すると思います。

＃例えば、GCログのローテートを毎日行う、等です。


CC BY-SA 4.0
2020-10-01T13:04:58.673
70868
2020-10-01T13:04:58.673
20098
70855
answer