-1

I am trying to write a Java Agent (for dynamic instrumentation), based off the following article: http://blog.javabenchmark.org/2013/05/java-instrumentation-tutorial.html

The problem is that I always get a ClassNotFoundException when I try to use the agent (other people who followed that article seemed to have the same problem, according to the comment section). The code for my Java agent is as follows:

Agent.java

package com.foo.tracer;

import java.lang.instrument.Instrumentation;

public class Agent {

    public static void premain(String agentArgs, Instrumentation inst) {

        inst.addTransformer(new MyClassFileTransformer());
    }
}

MyClassTransformer.java:

package com.foo.tracer;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import javassist.*;

public class MyClassFileTransformer implements ClassFileTransformer {

    public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

        byte[] byteCode = classfileBuffer;
        try {
            // if I remove this line, everything works
            ClassPool cp = ClassPool.getDefault();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return byteCode;
    }
}

I build the project using Maven (with "mvn package"):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.foo.tracer</groupId>
  <artifactId>tracer</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>tracer</name>
  <url>http://maven.apache.org</url>

  <build>
      <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <executions>
                <execution>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <archive>
                            <manifestEntries>
                                <premain-class>com.foo.tracer.Agent</premain-class>
                            </manifestEntries>
                        </archive>
                    </configuration>
                </execution>
            </executions>
        </plugin>
      </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.14.0-GA</version>
        <type>jar</type>
    </dependency>

  </dependencies>

</project>

I invoke the agent as follows:

$ java -verbose:class -javaagent:PATH/tracer-1.0-SNAPSHOT.jar -jar my-app-1.0-SNAPSHOT.jar | grep -iE "(foo|javassist)"
[Loaded com.foo.tracer.Agent from file:[CUT]/tracer-1.0-SNAPSHOT.jar]
[Loaded com.foo.tracer.MyClassFileTransformer from file:[CUT]/tracer-1.0-SNAPSHOT.jar]
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:386)
    at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401)
Caused by: java.lang.NoClassDefFoundError: javassist/ClassPool
    at com.foo.tracer.Agent.premain(Agent.java:11)
    ... 6 more
Caused by: java.lang.ClassNotFoundException: javassist.ClassPool
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 7 more

As you can see, my own classes are loaded by the ClassLoader, but for some reason the .class Files in javassist.jar are not loaded (I think that javaassist.jar, which is packaged into tracer-1.0-SNAPSHOT.jar, is not processed by the ClassLoader). I guess there is something wrong with my pom.xml file. Can someone tell me how I can fix this?

Directory structure (in case this is relevant):

$ tree
.
├── pom.xml
└── src
    ├── javassist.jar
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── foo
    │   │           └── tracer
    │   │               ├── Agent.java
    │   │               └── MyClassFileTransformer.java
    │   └── resources
    │       └── javassist.jar
    ├── META-INF
    │   └── MANIFEST.MF
    └── test
        └── java
            └── com
                └── tracer
                    └── AppTest.java
icarus
  • 39
  • 4

1 Answers1

-1

You are assuming that the files in javaassist.jar are being packaged into tracer-1.0-SNAPSHOT.jar, but that assumption is incorrect.

See How can I create an executable JAR with dependencies using Maven? for some ideas on how you can make that happen.

  • Please read [How do I write a good answer?](http://stackoverflow.com/help/how-to-answer) before attempting to answer more questions. –  Apr 23 '18 at 19:14
  • Please read [What types of questions should I avoid answering?](https://meta.stackoverflow.com/questions/260087/add-what-types-of-questions-should-i-avoid-answering-to-the-help-center) before attempting to answer more questions. Duplicates should not be answered, they should be flagged as such. –  Apr 23 '18 at 19:14