How to find list of java agents attached with a running JVM?

java

Solution

(This question is similar to Can a JVM retrieve a list of agents that have been loaded into it via the attach api?). For the sake of completeness, I will add this answer to both questions.)

Checking agents that have been added via command-line:

If you are interested in agents that were added to using the command line interface, you can check them by using the `RuntimeMXBean`.

This bean offers the method `getInputArguments`, which returns a list of all VM arguments. You can iterate over the list and check it for the arguments `agentpath`, `agentlib` and `javaagent`, similar to the following code snippet:

    RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
    List<String> jvmArgs = runtimeMXBean.getInputArguments();
    System.out.println("JVM arguments:");
    for (String arg : jvmArgs) {
        if (arg.startsWith("-agentpath") || arg.startsWith("-agentlib") || arg.startsWith("-javaagent")) {
            System.out.print("***** ");
        }

        System.out.print(arg);

        if (arg.startsWith("-agentpath") || arg.startsWith("-agentlib") || arg.startsWith("-javaagent")) {
            System.out.println(" *****");
        } else {
            System.out.println();
        }
    }

Checking agents that have been added using the Attach API:

If you are interested in the agents that have been added to an application at run time using the Attach API, you can use the `DiagnosticCommandMBean`. This bean offers a diagnostic command called `vmDynlib`, a parameterless method that returns a `String` that list all dynamically loaded libraries.

Here is a snippet that prints all dynamic libraries loaded by the application's VM:

ObjectName diagnosticsCommandName = new ObjectName("com.sun.management:type=DiagnosticCommand");
String operationName = "vmDynlibs";
String result = (String) ManagementFactory.getPlatformMBeanServer().invoke(diagnosticsCommandName, operationName, null, null);
System.out.println(result);

This results in an output similar to this one:

Dynamic libraries:
0x00007ff7b8600000 - 0x00007ff7b8637000     C:\Program Files\Java\jdk1.8.0_181\bin\java.exe
0x00007ffdfeb00000 - 0x00007ffdfecf0000     C:\WINDOWS\SYSTEM32\ntdll.dll
0x00007ffdfe300000 - 0x00007ffdfe3b2000     C:\WINDOWS\System32\KERNEL32.DLL
0x00007ffdfbb30000 - 0x00007ffdfbdd3000     C:\WINDOWS\System32\KERNELBASE.dll
0x00007ffdfe950000 - 0x00007ffdfe9f3000     C:\WINDOWS\System32\ADVAPI32.dll
...

You can then check this text if it contains a certain `.so` or `.dll` file.

The same inspection can be performed non-programatically.

For this, you can use the `jconsole` tool.

Connect to a VM, switch to the tab `MBeans`, select `com.sun.management`, select `DiagnosticCommand`, select `Operations`, select `vmDynlibs`, and invoke it.

In the image, you can see one of my test agents attached to the application. The agent was attached using the `Attach API`, thus this agent would not be visible by checking the application's command line arguments (i.e., no `-agentpath=...` would be seen on the arguments) but is only visible as dynamically loaded library.

Problem

I am trying to debug an issue with the one of the java agents added to the production JVM. In the start up script for the application java agent is properly added and has been working on other environments. But in production this agent does not seems to be working. Is there any way to find list of java agents added ?

Original source