13

独自のプロファイラーを構築し、JVMTI API を使用してネイティブ ライブラリ エージェントを構築します。このエージェントは、追加パラメーター -agentlib を使用して、JVM と一緒に開始できます。さらに、実行中の JVM にエージェントを挿入できるAttach API があります。次のコードを使用して、この機能をプロファイラーに実装したいと考えました。

try {
    String pid = VirtualMachine.list().get(0).id();
    VirtualMachine vm = VirtualMachine.attach(pid);
    vm.loadAgentLibrary("agent");
} catch (AgentLoadException e1) {
    e1.printStackTrace();
} catch (AgentInitializationException e1) {
    e1.printStackTrace();
} catch (IOException e1) {
    e1.printStackTrace();
} catch (AttachNotSupportedException e) {
    e.printStackTrace();
}

それは何をするためのものか?利用可能な実行中のすべての仮想マシン ( VirtualMachine.list()) から最初の仮想マシンを選択し、それにアタッチしてエージェントをロードしようとします。libagent.so という名前の UNIX システム上のエージェントは見つかりますが、エージェントをロードしようとすると、次の例外がスローされます。

com.sun.tools.attach.AttachNotSupportedException:
   Unable to open socket file:
      target process not responding or HotSpot VM not loaded.

ソース コードを調べると、という名前のファイルが見つからないため、この例外がスローされます.java_pid<pid>。ドキュメントには、この種のファイルに関する多くの情報が見つかりませんでした。この種のファイルはもう使われていないとよく耳にしますが、私は Java 1.6 を実行しています。

また、他の JVM にアタッチしようとしました。実際、このアタッチ プロセスを動的に保ちました。テスト上の理由から、任意の JVM にアタッチしようとしました。


これは、 sun.tools.attach: LinuxVirtualMachine.javaから取られた、例外につながるコードです:

    // Return the socket file for the given process.
    // Checks working directory of process for .java_pid<pid>. If not
    // found it looks in /tmp.
    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 /tmp
           path = "/tmp/" + fn;
           f = new File(path);
           if (!f.exists()) {
               return null;            // not found
           }
       }
       return path;
   }

それは、ルートから/proc/<pid>ディレクトリを探していると言います。JDK7 の変更セットを見ると、コードJDK7 Changeset to LinuxVirtualMachine に変更を加えているようです。

4

2 に答える 2

29

この同じ問題が発生しました。

スレッド「メイン」での例外 com.sun.tools.attach.AttachNotSupportedException: ソケット ファイルを開けません: ターゲット プロセスが応答していないか、HotSpot VM がロードされていません

解決策は、いくつかの重いグーグルを実行することで見つかりました。

最初の答えはhttp://www.jvmmonitor.org/doc/index.html でした。バグがあるようです:

「ソケット ファイルを開けません: ターゲット プロセスが応答していないか、Hotspot VM がロードされていません」という追加のメッセージが表示される場合は、アプリケーションが /tmp/.java_pid1234 のようなソケット ファイルの作成に応答しなかったかのどちらかです (ハングアップ、ファイル システムのアクセス許可が原因であるなど)。 )、または JVM Monitor が作成されたソケット ファイルを見つけることができませんでした (たとえば、バグ 7009828 が原因で)。

次に、さらに検索した後、同じ症状「ソケットファイルを開けません」(https://github.com/rhuss/jolokia/issues/34) を持つ別のツールの会話を github で見つけました。

jgreen: 原因: com.sun.tools.attach.AttachNotSupportedException: ソケット ファイルを開けません: ターゲット プロセスが応答していないか、HotSpot VM がロードされていません

jgreen: 正しく動作していますが、activemq とまったく同じユーザーとして起動した場合のみです。ルートが機能しない

この最後の部分が解決策でした。この .attach 呼び出しを成功させる唯一の方法は、jvm を実行するプロセスを所有するユーザーと同じユーザーとして attach を呼び出す Java コードを実行することでした。私の場合、それは activemq ユーザーでした。

System.out.println("HEAP: " + ManagementFactory.getMemoryMXBean().getHeapMemoryUsage());

HEAP: init = 27127296(26491K) used = 3974200(3881K) committed = 26345472(25728K) max = 675086336(659264K)
于 2012-12-20T14:31:14.153 に答える
3

実行中のJVM指定している可能性があり、Java 6 Update 23または24を使用していると思われますその場合は、実行中のインスタンスをUpdate25にアップグレードする必要があります。-Djava.io.tmpdir

私が見たこの問題への唯一の参照はJstackであり、JstatはJDK6u23へのアップグレードで動作を停止しました。Update 23とjstackが失敗するという同じ問題を確実に確認しました。ここでは、23より前は正常に機能し、25でも機能します。またVirtualMachine.attach(pid)、23に対して試したところ、を使用すると失敗します-Djava.io.tmpdir。25で動作します。

于 2011-04-29T06:08:51.990 に答える