Skip to content

Commit 1cfb43c

Browse files
agent example
1 parent 23ea412 commit 1cfb43c

File tree

7 files changed

+305
-0
lines changed

7 files changed

+305
-0
lines changed

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
target
2+
dependency-reduced-pom.xml
3+
/.metadata/
4+
/.recommenders/
5+
.classpath
6+
.project
7+
.settings
8+
.idea/
9+
*.iml
10+
.DS_Store
11+
html_docs
12+
docs/html/
13+
**/__pycache__/
14+
.m2/
15+
fetch.log
16+
.ci/.aws

pom.xml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4+
5+
<modelVersion>4.0.0</modelVersion>
6+
<groupId>javaagent-examples</groupId>
7+
<artifactId>javaagent-examples</artifactId>
8+
<name>javaagent-examples</name>
9+
<version>1.0</version>
10+
<description>javaagent-examples</description>
11+
<packaging>jar</packaging>
12+
13+
<build>
14+
<finalName>javaagent-examples</finalName>
15+
<plugins>
16+
<plugin>
17+
<groupId>org.apache.maven.plugins</groupId>
18+
<artifactId>maven-compiler-plugin</artifactId>
19+
<configuration>
20+
<source>1.6</source>
21+
<target>1.6</target>
22+
</configuration>
23+
</plugin>
24+
<plugin>
25+
<groupId>org.apache.maven.plugins</groupId>
26+
<artifactId>maven-assembly-plugin</artifactId>
27+
<executions>
28+
<execution>
29+
<goals>
30+
<goal>attached</goal>
31+
</goals>
32+
<phase>package</phase>
33+
<configuration>
34+
<descriptorRefs>
35+
<descriptorRef>jar-with-dependencies</descriptorRef>
36+
</descriptorRefs>
37+
<archive>
38+
<manifest>
39+
<mainClass>name.dhruba.javaagent.MyMainClass</mainClass>
40+
</manifest>
41+
<manifestEntries>
42+
<Premain-Class>name.dhruba.javaagent.MyJavaAgent</Premain-Class>
43+
<Agent-Class>name.dhruba.javaagent.MyJavaAgent</Agent-Class>
44+
<Can-Redefine-Classes>true</Can-Redefine-Classes>
45+
<Can-Retransform-Classes>true</Can-Retransform-Classes>
46+
</manifestEntries>
47+
</archive>
48+
</configuration>
49+
</execution>
50+
</executions>
51+
</plugin>
52+
</plugins>
53+
</build>
54+
55+
<dependencies>
56+
57+
<dependency>
58+
<groupId>junit</groupId>
59+
<artifactId>junit</artifactId>
60+
<version>4.7</version>
61+
<scope>test</scope>
62+
</dependency>
63+
64+
<dependency>
65+
<groupId>asm</groupId>
66+
<artifactId>asm</artifactId>
67+
<version>3.2</version>
68+
</dependency>
69+
70+
<dependency>
71+
<groupId>com.sun</groupId>
72+
<artifactId>tools</artifactId>
73+
<version>1.6.0</version>
74+
<scope>system</scope>
75+
<systemPath>${java.home}/../lib/tools.jar</systemPath>
76+
</dependency>
77+
78+
<dependency>
79+
<groupId>org.slf4j</groupId>
80+
<artifactId>jcl-over-slf4j</artifactId>
81+
<version>1.5.8</version>
82+
<scope>runtime</scope>
83+
</dependency>
84+
85+
<dependency>
86+
<groupId>ch.qos.logback</groupId>
87+
<artifactId>logback-classic</artifactId>
88+
<version>0.9.9</version>
89+
</dependency>
90+
91+
</dependencies>
92+
93+
</project>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package name.dhruba.javaagent;
2+
3+
import java.lang.instrument.ClassFileTransformer;
4+
import java.lang.instrument.IllegalClassFormatException;
5+
import java.security.ProtectionDomain;
6+
7+
import org.objectweb.asm.ClassWriter;
8+
import org.objectweb.asm.Label;
9+
import org.objectweb.asm.MethodVisitor;
10+
import org.objectweb.asm.Opcodes;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
14+
public class MyClassFileTransformer implements ClassFileTransformer, Opcodes {
15+
16+
static final Logger logger = LoggerFactory.getLogger(MyClassFileTransformer.class);
17+
18+
@Override
19+
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
20+
ProtectionDomain protectionDomain, byte[] classfileBuffer)
21+
throws IllegalClassFormatException {
22+
logger.info("class file transformer invoked for className: {}", className);
23+
24+
if (className.equals("name/dhruba/user/MyUser")) {
25+
26+
ClassWriter cw = new ClassWriter(0);
27+
MethodVisitor mv;
28+
29+
cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "name/dhruba/user/MyUser", null,
30+
"java/lang/Object", null);
31+
32+
cw.visitSource(null, null);
33+
34+
{
35+
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
36+
mv.visitCode();
37+
Label l0 = new Label();
38+
mv.visitLabel(l0);
39+
mv.visitLineNumber(3, l0);
40+
mv.visitVarInsn(ALOAD, 0);
41+
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
42+
mv.visitInsn(RETURN);
43+
Label l1 = new Label();
44+
mv.visitLabel(l1);
45+
mv.visitLocalVariable("this", "Lname/dhruba/user/MyUser;", null, l0, l1, 0);
46+
mv.visitMaxs(1, 1);
47+
mv.visitEnd();
48+
}
49+
{
50+
mv = cw.visitMethod(ACC_PUBLIC, "getName", "()Ljava/lang/String;", null, null);
51+
mv.visitCode();
52+
Label l0 = new Label();
53+
mv.visitLabel(l0);
54+
mv.visitLineNumber(6, l0);
55+
mv.visitLdcInsn("bar");
56+
mv.visitInsn(ARETURN);
57+
Label l1 = new Label();
58+
mv.visitLabel(l1);
59+
mv.visitLocalVariable("this", "Lname/dhruba/user/MyUser;", null, l0, l1, 0);
60+
mv.visitMaxs(1, 1);
61+
mv.visitEnd();
62+
}
63+
cw.visitEnd();
64+
65+
return cw.toByteArray();
66+
}
67+
68+
return classfileBuffer;
69+
}
70+
71+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package name.dhruba.javaagent;
2+
3+
import java.lang.instrument.Instrumentation;
4+
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
8+
public class MyJavaAgent {
9+
10+
static final Logger logger = LoggerFactory.getLogger(MyJavaAgent.class);
11+
12+
private static Instrumentation instrumentation;
13+
14+
/**
15+
* JVM hook to statically load the javaagent at startup.
16+
*
17+
* After the Java Virtual Machine (JVM) has initialized, the premain method
18+
* will be called. Then the real application main method will be called.
19+
*
20+
* @param args
21+
* @param inst
22+
* @throws Exception
23+
*/
24+
public static void premain(String args, Instrumentation inst) throws Exception {
25+
logger.info("premain method invoked with args: {} and inst: {}", args, inst);
26+
instrumentation = inst;
27+
instrumentation.addTransformer(new MyClassFileTransformer());
28+
}
29+
30+
/**
31+
* JVM hook to dynamically load javaagent at runtime.
32+
*
33+
* The agent class may have an agentmain method for use when the agent is
34+
* started after VM startup.
35+
*
36+
* @param args
37+
* @param inst
38+
* @throws Exception
39+
*/
40+
public static void agentmain(String args, Instrumentation inst) throws Exception {
41+
logger.info("agentmain method invoked with args: {} and inst: {}", args, inst);
42+
instrumentation = inst;
43+
instrumentation.addTransformer(new MyClassFileTransformer());
44+
}
45+
46+
/**
47+
* Programmatic hook to dynamically load javaagent at runtime.
48+
*/
49+
public static void initialize() {
50+
if (instrumentation == null) {
51+
MyJavaAgentLoader.loadAgent();
52+
}
53+
}
54+
55+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package name.dhruba.javaagent;
2+
3+
import java.lang.management.ManagementFactory;
4+
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
8+
import com.sun.tools.attach.VirtualMachine;
9+
10+
public class MyJavaAgentLoader {
11+
12+
static final Logger logger = LoggerFactory.getLogger(MyJavaAgentLoader.class);
13+
14+
private static final String jarFilePath = "/home/dhruba/.m2/repository/"
15+
+ "javaagent-examples/javaagent-examples/1.0/"
16+
+ "javaagent-examples-1.0-jar-with-dependencies.jar";
17+
18+
public static void loadAgent() {
19+
logger.info("dynamically loading javaagent");
20+
String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
21+
int p = nameOfRunningVM.indexOf('@');
22+
String pid = nameOfRunningVM.substring(0, p);
23+
24+
try {
25+
VirtualMachine vm = VirtualMachine.attach(pid);
26+
vm.loadAgent(jarFilePath, "");
27+
vm.detach();
28+
} catch (Exception e) {
29+
throw new RuntimeException(e);
30+
}
31+
}
32+
33+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package name.dhruba.javaagent;
2+
3+
import java.util.Arrays;
4+
5+
import name.dhruba.user.MyUser;
6+
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
10+
public class MyMainClass {
11+
12+
static final Logger logger = LoggerFactory.getLogger(MyMainClass.class);
13+
14+
static {
15+
MyJavaAgent.initialize();
16+
}
17+
18+
/**
19+
* Main method.
20+
*
21+
* @param args
22+
*/
23+
public static void main(String[] args) {
24+
logger.info("main method invoked with args: {}", Arrays.asList(args));
25+
logger.info("userName: {}", new MyUser().getName());
26+
}
27+
28+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package name.dhruba.user;
2+
3+
public class MyUser {
4+
5+
public String getName() {
6+
return "foo";
7+
}
8+
9+
}

0 commit comments

Comments
 (0)