Skip to content

Commit d282d64

Browse files
first version
1 parent 1cfb43c commit d282d64

File tree

11 files changed

+176
-86
lines changed

11 files changed

+176
-86
lines changed

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,24 @@
1-
# agent-attach-java
1+
# agent-attach-java
2+
3+
## 原理
4+
Attach 根本原理是使用文件 Socket 通讯, 就是往一个文件中写入 `load instrument xxx.jar=params`, 再给 jvm 一个 SIGQUIT 信号, 之后 jvm 读取 socket 文件, 加载对应的 agent.
5+
6+
## 如何在 jvm 运行时动态添加 agent
7+
1. 首先下载***指定***的 ddtrace , 并放到 /usr/local/ddtrace/
8+
```shell
9+
mkdir -p /usr/local/ddtrace
10+
cd /usr/local/ddtrace
11+
wget https://github.com/GuanceCloud/dd-trace-java/releases/download/v0.113.0-attach/dd-java-agent.jar
12+
13+
```
14+
15+
2. 启动 java 程序
16+
3. 启动 agent-attach-java.jar
17+
```shell
18+
# 命令的参数有三个 options download agent-jar 没有的话 都是默认值
19+
# options=""
20+
# download ="" 下个版本(指定版本下载)
21+
# agent-jar="/usr/local/ddtrace/dd-java-agent.jar"
22+
java -jar agent-attach-java.jar -options "dd.agent.port=9529"
23+
24+
```
5.4 MB
Binary file not shown.

pom.xml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,22 @@
33
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
44

55
<modelVersion>4.0.0</modelVersion>
6-
<groupId>javaagent-examples</groupId>
7-
<artifactId>javaagent-examples</artifactId>
8-
<name>javaagent-examples</name>
6+
<groupId>agent-attach-java</groupId>
7+
<artifactId>agent-attach-java</artifactId>
8+
<name>agent-attach-java</name>
99
<version>1.0</version>
10-
<description>javaagent-examples</description>
10+
<description>agent-attach-java</description>
1111
<packaging>jar</packaging>
1212

1313
<build>
14-
<finalName>javaagent-examples</finalName>
14+
<finalName>agent-attach-java</finalName>
1515
<plugins>
1616
<plugin>
1717
<groupId>org.apache.maven.plugins</groupId>
1818
<artifactId>maven-compiler-plugin</artifactId>
1919
<configuration>
20-
<source>1.6</source>
21-
<target>1.6</target>
20+
<source>1.8</source>
21+
<target>1.8</target>
2222
</configuration>
2323
</plugin>
2424
<plugin>
@@ -38,12 +38,12 @@
3838
<manifest>
3939
<mainClass>name.dhruba.javaagent.MyMainClass</mainClass>
4040
</manifest>
41-
<manifestEntries>
41+
<!-- <manifestEntries>
4242
<Premain-Class>name.dhruba.javaagent.MyJavaAgent</Premain-Class>
4343
<Agent-Class>name.dhruba.javaagent.MyJavaAgent</Agent-Class>
4444
<Can-Redefine-Classes>true</Can-Redefine-Classes>
4545
<Can-Retransform-Classes>true</Can-Retransform-Classes>
46-
</manifestEntries>
46+
</manifestEntries>-->
4747
</archive>
4848
</configuration>
4949
</execution>
@@ -68,11 +68,11 @@
6868
</dependency>
6969

7070
<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>
71+
<groupId>io.earcam.wrapped</groupId>
72+
<artifactId>com.sun.tools.attach</artifactId>
73+
<version>1.8.0_jdk8u131-b11</version>
74+
<scope>compile</scope>
75+
<type>jar</type>
7676
</dependency>
7777

7878
<dependency>

src/main/java/META-INF/MANIFEST.MF

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Manifest-Version: 1.0
2+
Main-Class: name.dhruba.javaagent.MyMainClass
3+

src/main/java/name/dhruba/javaagent/MyClassFileTransformer.java renamed to src/main/java/name/dhruba/javaagent/ClassFileTransformer.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
11
package name.dhruba.javaagent;
22

3-
import java.lang.instrument.ClassFileTransformer;
43
import java.lang.instrument.IllegalClassFormatException;
54
import java.security.ProtectionDomain;
65

7-
import org.objectweb.asm.ClassWriter;
8-
import org.objectweb.asm.Label;
9-
import org.objectweb.asm.MethodVisitor;
106
import org.objectweb.asm.Opcodes;
117
import org.slf4j.Logger;
128
import org.slf4j.LoggerFactory;
139

14-
public class MyClassFileTransformer implements ClassFileTransformer, Opcodes {
10+
public class ClassFileTransformer implements java.lang.instrument.ClassFileTransformer, Opcodes {
1511

16-
static final Logger logger = LoggerFactory.getLogger(MyClassFileTransformer.class);
12+
static final Logger logger = LoggerFactory.getLogger(ClassFileTransformer.class);
1713

1814
@Override
1915
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
2016
ProtectionDomain protectionDomain, byte[] classfileBuffer)
2117
throws IllegalClassFormatException {
2218
logger.info("class file transformer invoked for className: {}", className);
19+
/*
2320
2421
if (className.equals("name/dhruba/user/MyUser")) {
2522
@@ -64,6 +61,7 @@ public byte[] transform(ClassLoader loader, String className, Class<?> classBein
6461
6562
return cw.toByteArray();
6663
}
64+
*/
6765

6866
return classfileBuffer;
6967
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package name.dhruba.javaagent;
2+
3+
public class Config {
4+
private String options;
5+
6+
private String downloadAddress;
7+
8+
private String agentJar;
9+
10+
public String getOptions() {
11+
return options;
12+
}
13+
14+
public String getDownloadAddress() {
15+
return downloadAddress;
16+
}
17+
18+
public String getAgentJar() {
19+
return agentJar;
20+
}
21+
22+
private Config(String options,String downloadAddress,String agentJar){
23+
this.options = options;
24+
this.downloadAddress = downloadAddress;
25+
this.agentJar = agentJar;
26+
}
27+
28+
static Config parse(String... args){
29+
String option = "";
30+
String downloadAddr= "";
31+
String currentArg = "";
32+
String agentJar= "";
33+
for(String arg : args){
34+
if (arg.startsWith("-")){
35+
currentArg =arg;
36+
}else {
37+
switch (currentArg){
38+
case "options":
39+
option = arg;
40+
case "download":
41+
downloadAddr = arg;
42+
case "agent-jar":
43+
agentJar = arg;
44+
}
45+
}
46+
}
47+
48+
return new Config(option,downloadAddr,agentJar);
49+
}
50+
51+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package name.dhruba.javaagent;
2+
3+
import java.lang.management.ManagementFactory;
4+
import java.util.List;
5+
import java.util.Properties;
6+
7+
import com.sun.tools.attach.VirtualMachineDescriptor;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
11+
import com.sun.tools.attach.VirtualMachine;
12+
13+
public class JavaAgentLoader {
14+
static final Logger logger = LoggerFactory.getLogger(JavaAgentLoader.class);
15+
16+
private static final String jarFilePath = "/usr/local/ddtrace/dd-java-agent.jar";
17+
18+
public static void loadAgent(String agentJar ,String options) {
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+
System.out.println("------------------into-------------");
24+
System.out.println("------------------p-------------"+p);
25+
System.out.println("------------------pid-------------"+pid);
26+
System.out.println("------------------args-------------"+options);
27+
28+
try {
29+
List<VirtualMachineDescriptor> list = VirtualMachine.list();
30+
for (int i = 0; i < list.size(); i++) {
31+
VirtualMachineDescriptor virtualMachineDescriptor = list.get(i);
32+
String version = virtualMachineDescriptor.id();
33+
System.out.println(version);
34+
System.out.println(virtualMachineDescriptor.id());
35+
System.out.println(virtualMachineDescriptor.displayName());
36+
System.out.println(virtualMachineDescriptor.toString());
37+
38+
VirtualMachine attach = VirtualMachine.attach(version);
39+
if (agentJar != null && !agentJar.equals("")){
40+
attach.loadAgent(jarFilePath, options);
41+
}else {
42+
attach.loadAgent(agentJar, options);
43+
}
44+
45+
46+
Properties properties = attach.getAgentProperties();
47+
Properties sysproperties = attach.getSystemProperties();
48+
System.out.println( properties.toString());
49+
System.out.println( sysproperties.toString());
50+
System.out.println("DdTrace attach agent to displayName is:"+virtualMachineDescriptor.displayName());
51+
52+
attach.detach();
53+
}
54+
55+
// -------------
56+
// VirtualMachine vm = VirtualMachine.attach(pid);
57+
// vm.loadAgent(jarFilePath, "Ddd.env:test,Ddd.service.name:demo001,Ddd.agent.port:9529");// 参数
58+
// vm.detach();
59+
} catch (Exception e) {
60+
throw new RuntimeException(e);
61+
}
62+
}
63+
}

src/main/java/name/dhruba/javaagent/MyJavaAgent.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ public class MyJavaAgent {
2121
* @param inst
2222
* @throws Exception
2323
*/
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-
}
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+
// }
2929

3030
/**
3131
* JVM hook to dynamically load javaagent at runtime.
@@ -37,19 +37,14 @@ public static void premain(String args, Instrumentation inst) throws Exception {
3737
* @param inst
3838
* @throws Exception
3939
*/
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-
}
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+
// }
4545

4646
/**
4747
* Programmatic hook to dynamically load javaagent at runtime.
4848
*/
49-
public static void initialize() {
50-
if (instrumentation == null) {
51-
MyJavaAgentLoader.loadAgent();
52-
}
53-
}
5449

5550
}

src/main/java/name/dhruba/javaagent/MyJavaAgentLoader.java

Lines changed: 0 additions & 33 deletions
This file was deleted.

src/main/java/name/dhruba/javaagent/MyMainClass.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,26 @@
22

33
import java.util.Arrays;
44

5-
import name.dhruba.user.MyUser;
6-
75
import org.slf4j.Logger;
86
import org.slf4j.LoggerFactory;
97

108
public class MyMainClass {
119

1210
static final Logger logger = LoggerFactory.getLogger(MyMainClass.class);
1311

14-
static {
15-
MyJavaAgent.initialize();
16-
}
17-
1812
/**
1913
* Main method.
20-
*
14+
*
2115
* @param args
2216
*/
2317
public static void main(String[] args) {
18+
Config config = Config.parse(args);
19+
// todo load agent ddtrace
20+
21+
// MyJavaAgent.initialize(config.getAgentJar(),config.getOptions());
22+
JavaAgentLoader.loadAgent(config.getAgentJar(),config.getOptions());
2423
logger.info("main method invoked with args: {}", Arrays.asList(args));
25-
logger.info("userName: {}", new MyUser().getName());
24+
// logger.info("userName: {}", new MyUser().getName());
2625
}
2726

2827
}

0 commit comments

Comments
 (0)