Repository navigation
Expand file tree
/
Copy path.tool.yaml
More file actions
136 lines (131 loc) · 5.05 KB
/
Copy path.tool.yaml
File metadata and controls
136 lines (131 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
tag: experimental
maven_coordinates: me.bechberger:meta-agent
tagline: Java agent that instruments other Java agents — wraps every ClassFileTransformer it finds
and records bytecode diffs viewable via a built-in web UI. Shows exactly what Mockito, Dynatrace,
async-profiler, or any other agent does to your classes at runtime.
tagline_short: Instrument your Java agents — record and diff the bytecode transformations they apply.
when_to_use:
- You want to see exactly what bytecode transformations a Java agent (Mockito, Dynatrace, async-profiler) applies
- You are debugging unexpected behaviour caused by another agent's class instrumentation
- You want to intercept or block specific ClassFileTransformer registrations at runtime
when_not_to_use:
- You only want to view class bytecode without running another agent — use a decompiler instead
install:
- label: Build from source
lang: bash
code: |
git clone https://github.com/parttimenerd/meta-agent
cd meta-agent
mvn package -DskipTests
# JAR: target/meta-agent.jar
- label: Maven plugin (for tests)
lang: xml
code: |
<plugin>
<groupId>me.bechberger</groupId>
<artifactId>meta-agent-maven-plugin</artifactId>
<version>VERSION</version>
<executions>
<execution>
<phase>validate</phase>
<goals><goal>meta-agent</goal></goals>
</execution>
</executions>
<configuration>
<server>true</server>
</configuration>
</plugin>
usage:
- label: Run with agent
lang: bash
code: |
java -javaagent:target/meta-agent.jar=server -jar your-program.jar
# open http://localhost:7071 to browse transformations
how_to:
- title: View what an agent does to your classes
body: |
Attach meta-agent alongside the agent you want to inspect. Open the built-in web UI to browse
decompiled bytecode diffs grouped by transformer or by class:
```bash
java -javaagent:target/meta-agent.jar=server -jar your-program.jar
# custom port:
java -javaagent:target/meta-agent.jar=server,port=8080 -jar your-program.jar
```
Key endpoints at `http://localhost:7071`:
- `/instrumentators` — list all ClassFileTransformers that were registered
- `/full-diff/instrumentator?pattern=.*` — decompiled bytecode diff per transformer
- `/classes` — list all classes that were transformed
- `/full-diff/class?pattern=.*` — full diff across all classes and transformers
- `/all/decompile?pattern=<pattern>` — decompile matching classes
- title: Intercept or block transformer registrations with a callback
body: |
Implement `InstrumentationCallback` and pass it via the `cb` argument to observe or block
transformers. Note: `CallbackAction.IGNORE` suppresses the transformer (not `DENY`):
```java
public class MyHandler implements InstrumentationCallback {
@Override
public CallbackAction onAddTransformer(ClassFileTransformer transformer) {
System.err.println("New transformer: " + transformer.getClass().getName());
return CallbackAction.ALLOW; // or IGNORE to suppress it
}
@Override
public void onExistingTransformer(ClassFileTransformer transformer) {
System.err.println("Existing transformer: " + transformer.getClass().getName());
}
@Override
public CallbackAction onInstrumentation(ClassFileTransformer transformer,
ClassArtifact before, ClassArtifact after) {
System.out.println("Instrumenting: " + before.klass().getName());
return CallbackAction.ALLOW;
}
}
```
Pass the fully qualified class name via `cb`:
```bash
java -javaagent:target/meta-agent.jar=server,cb=com.example.MyHandler -jar your-program.jar
```
- title: Capture native agents too
body: |
Build the native component first, then load both agents:
```bash
cd native && make
# macOS:
java -agentpath:native/native_agent.dylib \
-javaagent:target/meta-agent.jar=server \
-jar your-program.jar
# Linux:
java -agentpath:native/native_agent.so \
-javaagent:target/meta-agent.jar=server \
-jar your-program.jar
```
- title: Add to Maven test runs
body: |
Use the Maven plugin to attach meta-agent automatically during `mvn test`:
```xml
<plugin>
<groupId>me.bechberger</groupId>
<artifactId>meta-agent-maven-plugin</artifactId>
<version>VERSION</version>
<executions>
<execution>
<phase>validate</phase>
<goals><goal>meta-agent</goal></goals>
</execution>
</executions>
<configuration>
<server>true</server>
<callbackClasses>
<callbackClass>com.example.MyHandler</callbackClass>
</callbackClasses>
</configuration>
</plugin>
```
Add the runtime dependency so your callback class can reference the API:
```xml
<dependency>
<groupId>me.bechberger</groupId>
<artifactId>meta-agent</artifactId>
<version>VERSION</version>
<scope>test</scope>
</dependency>
```