我正在尝试调试添加到生产JVM中的一个Java代理的问题。
在应用程序启动脚本中,Java代理已经被正确添加,并且在其他环境中一直工作。但是在生产环境中,这个代理似乎没有起作用。
有没有办法找到已添加的Java代理列表?
在应用程序启动脚本中,Java代理已经被正确添加,并且在其他环境中一直工作。但是在生产环境中,这个代理似乎没有起作用。
有没有办法找到已添加的Java代理列表?
(这个问题类似于JVM能否通过Attach API检索已加载的代理程序列表?为了完整起见,我将在两个问题中都添加此答案。)
如果您对使用命令行界面添加的代理程序有兴趣,可以使用RuntimeMXBean
来检查它们。
这个bean提供了getInputArguments
方法,它返回所有VM参数的列表。您可以遍历列表,并检查它是否包含参数agentpath
、agentlib
或javaagent
,就像以下代码片段一样:
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();
}
}
如果您对在运行时使用Attach API添加到应用程序中的代理感兴趣,您可以使用DiagnosticCommandMBean
。
此bean提供了一个名为vmDynlib
的诊断命令,它是一个无参数方法,返回一个String
,其中列出所有动态加载的库。
这里是一个代码片段,打印应用程序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);
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
...
接下来您可以检查此文本中是否包含某个.so
或.dll
文件。
同样的检查也可以非编程方式执行。
为此,您可以使用jconsole
工具。
连接到虚拟机,切换到选项卡MBeans
,选择com.sun.management
,选择DiagnosticCommand
,选择Operations
,选择vmDynlibs
,并调用它。
在图像中,您可以看到我测试代理程序之一连接到应用程序。
代理程序是使用Attach API
附加的,因此通过检查应用程序的命令行参数不会看到-agentpath=...
(即不会在参数上看到),但只能作为动态加载库显示。