You may have read that Mustang JDK now includes attach-on-demand. i.e., With the Mustang JDK you can now attach jconsole to any application, even if it wasn't launched with the magic -Dcom.sun.management.jmxremote. In fact, this is not specific to jconsole agent. You can load any suitably coded native or Java agent into running JVM using the attach API. Let us see how to write a simple "hello world"agent. A typical JVM agent would bytecode instrument classes on class load and/or when classes are being redefined. But, we are interested in just learning attach API. So, here is a simple agent that -- well, prints "Hello agent!"
import java.lang.instrument.*;
public class HelloWorldAgent {
/* NOTE: agentmain is the special method that
will be called when this agent is loaded */
public static void agentmain(String agentArgs, Instrumentation inst) {
System.out.println("Hello agent!");
if (agentArgs != null) {
System.out.println("my args are: " + agentArgs);
}
}
}
Compile the above program and create a jar manifest file like manifest.mf shown below:
Agent-Class: HelloWorldAgent
In the above manifest file, we identify HelloWorldAgent class to be the agent class.
Now, we can jar the code with the command:
jar cvfm helloAgent.jar manifest.mf HelloWorldAgent.class
Now, we have written a JVM agent that can loaded. How do we
load it on a running JVM? We use com.sun.tools.attach (a.k.a attach API)
API.
import com.sun.tools.attach.*;
public class Attach {
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.out.println("usage: java Attach ");
System.exit(1);
}
// This program accepts two parameters:
// 1. The pid of the JVM on which we want to load an agent
// 2. The full path of the agent jar file to be loaded
// JVM is identified by process id (pid).
VirtualMachine vm = VirtualMachine.attach(args[0]);
// load a specified agent onto the JVM
vm.loadAgent(args[1], null);
}
}
When compiling above code, you need to put tools.jar in classpath. I assume $JAVA_HOME
is where your JDK is installed.
javac -cp $JAVA_HOME/lib/tools.jar Attach.java
Now, we have
public class Test {
public static void main(String[] args) throws Exception {
System.out.println("Main...");
while(true);
}
}
After compiling and running the above Test program, we can note down the pid of it using jps utility.
Now, we can attach and load helloAgent.jar using the command:
java -cp $JAVA_HOME/lib/tools.jar:. Attach <pid-of-Test-program> <path-of-the-helloAgent-jar>
If everything goes well, you should see "Hello agent!" being printed from your Test program.