I just wanted to try myself with javassist, and began editing a library's method body. To hook into the library i attach an agent using the tools.jar, located in '%JAVA_HOME%..\lib\'.
But I dislike the idea of every pc I'm using this on having the jdk installed just for the tools.jar
Isn't there another way like extracting the input of the jar into my final jar?
I did so with javassist and it seems to work fine (IntelliJ did so. It has a nice function for it http://puu.sh/hoiCo/bf19853b12.png)
But doing so with the tools.jar ends in the program throwing an exception
Screenshot of the exception http://puu.sh/hoiGd/844567bca2.png
public static void main(String[] args){
if(args.length < 1){
log("No ProcessID set");
return;
}
String pid = args[0];
VirtualMachine vm = null;
try{
vm = VirtualMachine.attach(pid);
String filePath = AgentMain.class.getProtectionDomain().getCodeSource().getLocation().getPath();
filePath = URLDecoder.decode(filePath, "UTF-8");
if(filePath.startsWith("/")){
filePath = filePath.substring(1);
}
log("Loading Agent... [" + filePath + "]");
vm.loadAgent(filePath);
}catch(Exception ex){
log("VM connection error [" + pid + "]");
ex.printStackTrace();
}finally{
try{
if(vm != null) vm.detach();
}catch(Exception ex){}
}
}
This is my code used for injecting the agent.
It would be great if someone could help.
I hope you understand :)
This project might help you: orbit/agent-loader
public class HelloAgent
{
public static void agentmain(String agentArgs, Instrumentation inst)
{
System.out.println(agentArgs);
System.out.println("Hi from the agent!");
System.out.println("I've got instrumentation!: " + inst);
}
}
public static void main(String[] args)
{
AgentLoader.loadAgentClass(HelloAgent.class.getName(), "Hello!");
}
It bundles the VirtualMachine classes inside it so you don't need the tools jar to attach an agent in runtime.
It's on maven:
<dependency>
<groupId>com.ea.orbit</groupId>
<artifactId>orbit-agent-loader</artifactId>
<version>0.5.2</version>
</dependency>
It should be possible to bundle it with your application in a single jar.
From your comments it's not clear if you know this, but you can also run your program with the VM option:
-javaagent:your-agent.jar
On a side note: In Intellij you can set the default launchers for java program and unit tests to have the -javaagent:something.jar by default. It's interesting that the jar doesn't need to have the actual agent classes, it just needs the proper manifest entries. (Provided that your agent classes are somewhere in the classpath of the project/module that you are running).