sun.tools.attach.WindowsAttachProvider 无法实例化

sun.tools.attach.WindowsAttachProvider could not be instantiated

我目前正在编写一个将代理附加到 JVM 进程的附加程序,我一直 运行 关注这个问题。这是我的代码的简化版本:

import com.sun.tools.attach.VirtualMachine;

public class AgentAttacher {
    public static void main(String[] args) {
        try {
            String pid = "some-pid-determined-elsewhere";
            final VirtualMachine vm = VirtualMachine.attach(pid);
            vm.loadAgent("agent.jar");
            vm.detach();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

当运行 java -jar AgentAttacher.jar时,我得到以下错误:

java.util.ServiceConfigurationError: com.sun.tools.attach.spi.AttachProvider: Provider sun.tools.attach.WindowsAttachProvider could not be instantiated

我尝试将 JDK 的 lib 目录中的 tools.jar 添加到 CLASSPATH 环境变量中,包括在我的 Class-PathMANIFEST.MF,并使用 -cp 直接指定它,而 运行 JAR。我相当确定 tools.jar 正在加载,因为它在丢失时会给出不同的错误:

Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/attach/VirtualMachine

我在仅使用 VirtualMachine.list() 时也遇到 WindowsAttachProvider could not be instantiated 错误,所以我认为这与使用 attach() 和不正确的 PID 无关。


我尝试使用 Class.forName():

加载 class
public class AgentAttacher {
    public static void main(String[] args) {
        try {
            Class.forName("sun.tools.attach.WindowsAttachProvider");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我得到以下堆栈跟踪:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no attach in java.library.path
        at java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.lang.Runtime.loadLibrary0(Unknown Source)
        at java.lang.System.loadLibrary(Unknown Source)
        at sun.tools.attach.WindowsAttachProvider.<clinit>(WindowsAttachProvider.java:175)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Unknown Source)
        at JavaAttacker.main(JavaAttacker.java:4)

如果我不在 class 路径中包含 tools.jar,我会在此处得到不同的堆栈跟踪,因此我确定它正在加载:

java.lang.ClassNotFoundException: sun.tools.attach.WindowsAttachProvider
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Unknown Source)
        at JavaAttacker.main(JavaAttacker.java:4)

我的环境是 VirtualBox 上的 Windows 10 Pro (1809) 虚拟机 JDK & JRE 1.8.0_212.

在 Java 8 中,附件 API 是 JVM 默认不加载的单独 jar 的一部分。您必须将其显式包含在 class 路径中。通常,它位于您 JDK 家的 \lib 文件夹中:

java -cp %JAVA_HOME%\lib\tools.jar -jar AgentAttacher.jar

问题似乎出在 attach.dll 没有从 %JAVA_HOME%\jre\bin 加载。

运行 罐子为:

java -Djava.library.path="%JAVA_HOME%\jre\bin" -jar AgentAttacher.jar

似乎有效,只要在 Class-Path 下的我的 jar 清单中指定 tools.jar