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

时间:2019-07-12 12:18:20

标签: java instrumentation javaagents

我目前正在编写一个将代理程序附加到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的tools.jar目录中的lib添加到CLASSPATH环境变量中,并将其添加到Class-Path中的MANIFEST.MF中,并在运行JAR时使用-cp直接指定它。我相当确定tools.jar正在加载,因为它在丢失时会给出不同的错误:

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

仅使用WindowsAttachProvider could not be instantiated时也会出现VirtualMachine.list()错误,因此我认为这与使用带有错误PID的attach()无关。


我尝试使用Class.forName()加载类:

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)

如果我没有在类路径中包含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上带有JDK和JRE 1.8.0_212的Windows 10 Pro(1809)VM。

2 个答案:

答案 0 :(得分:1)

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

以以下方式运行jar:

java -Djava.library.path="%JAVA_HOME%\jre\bin" -jar AgentAttacher.jar
只要在我的jar清单中的tools.jar下指定了Class-Path

似乎就起作用了。

答案 1 :(得分:0)

在Java 8中,attach API是单独的jar的一部分,默认情况下,JVM不加载该jar。您将必须在类路径中明确包含它。通常,它位于JDK主目录的\lib文件夹中:

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