I have two separate projects in my IDE for the agent and for the loader that finds a target VM and loads the agent JAR.
agent.jar
in it.The resulting runnable loader structure looks like this:
loader.jar
├── META-INF
│ └── MANIFEST.MF
├── me.domain.loader
│ └── Main.class
└── agent.jar
├── META-INF
│ └── MANIFEST.MF
└── me.domain.agent
└── Agent.class
From the VirtualMachine#loadAgent(java.lang.String) specification, I need to provide a path to the JAR containing the agent as the first parameter.
However, when using Main.class.getResource("/agent.jar").getPath()
I'm getting an AgentLoadException: Agent JAR not found or no Agent-Class attribute
. What's the correct way to do that?
It looks like the agent JAR to be loaded must exist on disk. I've solved this issue by copying the embedded JAR resource into a temporary file:
private static String getTemporaryResource(String resourceName) {
// Read embedded resource from this JAR
InputStream resourceStream = Main.class.getResourceAsStream(resourceName);
if (resourceStream == null) {
throw new Exception("Resource not found in the JAR");
}
// Create a temporary file in %TEMP%/resource5513111026806316867.tmp
File temporaryFile = File.createTempFile("resource", null);
temporaryFile.deleteOnExit();
// Copy the resource data into the temporary file
Files.copy(resourceStream, temporaryFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
// Return the path to temporary file
return temporaryFile.getAbsolutePath();
}
I'm then using this temporary path to load the agent:
String tempAgentPath = getTemporaryResource("/agent.jar");
VirtualMachine targetVM = VirtualMachine.attach("1337");
targetVM.loadAgent(tempAgentPath);