AttachNotSupportedException due to missing java_pid file in Attach API

Konrad Reiche picture Konrad Reiche · Apr 24, 2011 · Viewed 17.6k times · Source

Building a profiler of my own, I use the JVMTI API to build a native library agent. This agent can be started together with the JVM by using the addition parameter -agentlib. In addition there is the Attach API which allows to inject an agent into a running JVM. I wanted to implement this feature to my profiler using the following code:

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();
}

What does it do? From all the available running virtual machines (VirtualMachine.list()) I choose the first one, attach to it and try to load my agent into it. The agent, on UNIX systems named libagent.so, can be found, but when trying to load the agent the following exception is thrown:

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

Looking into the source code, this exception is thrown, because it cannot find a file named .java_pid<pid>. I haven't found a lot information about this kind of file in the documentation. I often heard this kind of file is not used anymore, but I am running Java 1.6.

I also tried to attach to other JVMs, in fact I kept this attaching process dynamic, for testing reasons I just try to attach to any JVM.


This is the code which leads to the exception, taken from 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;
   }

It says, it is looking from root into the /proc/<pid> directory. Looking at a changeset of the JDK7 it seems they are making changes to the code JDK7 Changeset to LinuxVirtualMachine

Answer

kwoodson picture kwoodson · Dec 20, 2012

I experienced this same issue.

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

The solution was found doing some heavy googling.

First answer came http://www.jvmmonitor.org/doc/index.html . Appears there is a bug:

If you see the additional message "Unable to open socket file: target process not responding or Hotspot VM not loaded", either your application didn't respond creating a socket file like /tmp/.java_pid1234 (e.g. due to hangup, file system permission), or JVM Monitor was not able to find the created socket file (e.g. due to the bug 7009828).

Then after some more searching I found a conversation on github for another tool which had the same symptom "Unable to open socket file" (https://github.com/rhuss/jolokia/issues/34):

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

jgreen: right I have it working but only when lauching as the exact same user as activemq. root does not work

This last piece was the solution. The only way this .attach call would be successful was through running the java code that calls attach as the same user as the one who owned the process running the jvm. In my case it was the activemq user.

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

HEAP: init = 27127296(26491K) used = 3974200(3881K) committed = 26345472(25728K) max = 675086336(659264K)