Why does using the Java Attach API fail on linux? (even though maven build completes)

exception, java, maven, tools.jar

Solution

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>

Problem

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...

Original source