I've been using the Java Attach API (part of tools.jar) to attach to a running java process, and shut it down from within.
It works perfectly on Windows. However when trying to actually execute the attach code when running on linux I get a java.lang.NoClassDefFoundError
with the following stack trace for the cause...
java.lang.ClassNotFoundException:com.sun.tools.attach.VirtualMachine...
java.net.URLClassLoader$1.run(URLClassLoader.java:202)
java.security.AccessController.doPrivileged(Native Method)
java.net.URLClassLoader.findClass(URLClassLoader.java:190)
java.lang.ClassLoader.loadClass(ClassLoader.java:306)
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
java.lang.ClassLoader.loadClass(ClassLoader.java:247)
I'm using Maven and so far I have this section, in order to include tools.jar.
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.4.2</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
Notably the ${java.home} evaluates to the jre but even if I change it to a direct path to the jdk, the issue is the same.
I'm pretty stumped...
Turns out this was an issue with the maven build. The system scope requires the container to pass tools.jar on the classpath at launch. A simple java -jar
does not do this (and I don't want to add an explicit classpath argument).
The solution I put together to solve this issue is to have the maven build choose the location using profiles, then pre-install the jar in the local repo before the package phase (allowing the dependancy to just be normal dependancy).
PROFILES SECTION...
<profiles>
<profile>
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<properties>
<toolsjar>${java.home}/../lib/tools.jar</toolsjar>
</properties>
</profile>
<profile>
<id>osx_profile</id>
<activation>
<activeByDefault>false</activeByDefault>
<os>
<family>mac</family>
</os>
</activation>
<properties>
<toolsjar>${java.home}/../Classes/classes.jar</toolsjar>
</properties>
</profile>
</profiles>
INSTALL-FILE SECTION...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<id>jdk_tools</id>
<phase>prepare-package</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.4.2</version>
<packaging>jar</packaging>
<file>${toolsjar}</file>
</configuration>
</execution>
</executions>
</plugin>
DEPENDANCY
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.4.2</version>
</dependency>
来源:https://stackoverflow.com/questions/16379208/why-does-using-the-java-attach-api-fail-on-linux-even-though-maven-build-compl