How to put classes for javaagent in the classpath
Asked Answered
C

5

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 ;-)

Capernaum answered 8/4, 2013 at 6:28 Comment(2)
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 pluginCapernaum
please write it as answer and accept it, so that the other users can see the answer of your question.Permute
C
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.

Capernaum answered 8/4, 2013 at 20:16 Comment(1)
The <Premain-Class>test.agent.MyAgent</Premain-Class> is important ;-)Capernaum
C
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
Calica answered 19/3, 2016 at 13:21 Comment(1)
What if the agent and the project are in 2 separate jars ?Ganley
G
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>
Gustie answered 31/8, 2018 at 16:23 Comment(0)
A
1

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

Almuce answered 2/5, 2013 at 9:27 Comment(0)
L
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

Lookout answered 17/5, 2018 at 13:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.