17

I am trying to develop a javaagent that would instrument code with help of asm-4. For now I'm stucked with a pretty basic problem, the classloader for the javaagent doesn't see asm dependencies and therefor fails. Do I have to provide a jar-with-dependencies (aka maven build plugin) which contains all the needed classes by the agent, or is there another way to add classes to the java agent? Referencing the jar asm-all.jar directly in the classpath didn't help. Building jar-with-dependencies didn't help at first, because Premain-Class attribute couldn't be set with assembly plugin. Help is appreciated ;-)

2
  • 1
    ok, apparently I found the answer myself: <manifestEntries> <Premain-Class>test.agent.MyAgent</Premain-Class> </manifestEntries> <- the assembly plugin accepts same configuration options as the jar plugin Commented Apr 8, 2013 at 6:47
  • 1
    please write it as answer and accept it, so that the other users can see the answer of your question. Commented Apr 8, 2013 at 6:53

5 Answers 5

14

ok, found it by experimenting. The dependent classes should be part of the jar, which can be created by maven assembly plugin, for example:

 <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <index>true</index> <manifest> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> </manifest> <manifestEntries> <Premain-Class>test.agent.MyAgent</Premain-Class> </manifestEntries> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <!-- this is used for inheritance merges --> <phase>package</phase> <!-- append to the packaging phase. --> <goals> <goal>single</goal> <!-- goals == mojos --> </goals> </execution> </executions> </plugin> 

Use the jar as javaagent path and everything works fine.

Sign up to request clarification or add additional context in comments.

1 Comment

The <Premain-Class>test.agent.MyAgent</Premain-Class> is important ;-)
8

I followed this blog post. Here is how I made it work, to get the size of objects.

/MANIFEST.MF

Manifest-Version: 1.0 Premain-Class: ar.com.docdigital.InstrumentationApp Can-Redefine-Classes: true Can-Retransform-Classes: true Can-Set-Native-Method-Prefix: true 

in your pom.xml (Note we reference custom MANIFEST)

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifestFile> MANIFEST.MF </manifestFile> <manifest> <addClasspath>true</addClasspath> <mainClass> ar.com.docdigital.App </mainClass> </manifest> </archive> </configuration> </plugin> 

My Instrumentation Agent:

package ar.com.docdigital; import java.lang.instrument.Instrumentation; /** * * @author juan.fernandez */ public class InstrumentationApp { private static Instrumentation instrumentation; public static void premain(String args, Instrumentation inst) { instrumentation = inst; } public static long getObjectSize(Object o) { return instrumentation.getObjectSize(o); } } 

My main App:

package ar.com.docdigital;

import static ar.com.docdigital.InstrumentationApp.getObjectSize; /** * * @author juan.fernandez */ public class App { public static void main (String[] args) { System.out.println("Size of CoprimeLong: " + getObjectSize(new CoprimesList.CoprimeLong(1L))); System.out.println("Size of Long: " + getObjectSize(new Long(1L))); } } 

Putting all together & CLI output:

$ mvn package $ java -javaagent:target/primos-0.1.0-SNAPSHOT.jar -jar target/primos-0.1.0-SNAPSHOT.jar Size of CoprimeLong: 24 Size of Long: 24 

1 Comment

What if the agent and the project are in 2 separate jars ?
4

I used maven-jar-plugin for my CustomAgent. I dont have any dependent modules/jars so using an assembly plugin is an overkill.

<build> <sourceDirectory>src</sourceDirectory> <finalName>are-agent</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> </manifest> <manifestEntries> <Premain-Class>are.agent.CustomAgent</Premain-Class> <Can-Redefine-Classes>false</Can-Redefine-Classes> <Can-Retransform-Classes>true</Can-Retransform-Classes> </manifestEntries> </archive> </configuration> </plugin> </plugins> <build> 

Comments

1

I think you can specify Class-Path in the Manifest.mf file in the MyAgent.jar.

Comments

1

You should add Premain-Class entry to the manifest. I use gradle to build Java projects.

Add this to gradle.build

jar { manifest { attributes( "Premain-Class": "com.training.agent.agentapp.SimplestAgent", "Can-Redefine-Classes": false, "Can-Set-Native-Method-Prefix": false ) } } 

And then you can run it

java -javaagent:agent.jar -jar application.jar 

Mode details

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.