Я пытаюсь написать Java-агент (для динамического инструментария), основываясь на следующей статье: http://blog.javabenchmark.org/2013/05/java-instrumentation-tutorial.html
Проблема в том, что я всегда получаю ClassNotFoundException, когда пытаюсь использовать агент (другие люди, которые следили за этой статьей, похоже, имели ту же проблему, согласно разделу комментариев). Код моего Java-агента выглядит следующим образом:
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;
}
}
Я собираю проект с помощью Maven (с «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>
Я вызываю агент следующим образом:
$ 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
Как видите, мои собственные классы загружаются с помощью ClassLoader, но по какой-то причине файлы .class в javassist.jar не загружаются (я думаю, что javaassist.jar, который упакован в tracer-1.0-SNAPSHOT.jar, является не обрабатывается ClassLoader). Я думаю, что с моим файлом pom.xml что-то не так. Может кто подскажет, как я могу это исправить?
Структура каталогов (если это актуально):
$ 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




Вы предполагаете, что файлы в javaassist.jar упаковываются в tracer-1.0-SNAPSHOT.jar, но это предположение неверно.
См. Как я могу создать исполняемый JAR с зависимостями с помощью Maven? для некоторых идей о том, как вы можете это сделать.
Пожалуйста, прочтите На какие вопросы мне следует избегать?, прежде чем пытаться ответить на другие вопросы. На дубликаты отвечать не следует, они должны быть помечены как таковые.
Пожалуйста, прочтите Как мне написать хороший ответ?, прежде чем пытаться ответить на другие вопросы.