Skip to content

Commit 0125081

Browse files
committed
javassist asm bytebuddy 对 xxl、spring、quartz、simple 定时任务的代理实现
1 parent 38b5b4e commit 0125081

18 files changed

+167
-128
lines changed

pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@
7474
<artifactId>byte-buddy-agent</artifactId>
7575
<version>1.10.22</version>
7676
</dependency>
77+
<dependency>
78+
<groupId>org.reflections</groupId>
79+
<artifactId>reflections</artifactId>
80+
<version>0.9.11</version>
81+
<exclusions>
82+
<exclusion>
83+
<artifactId>javassist</artifactId>
84+
<groupId>org.javassist</groupId>
85+
</exclusion>
86+
</exclusions>
87+
</dependency>
7788
</dependencies>
7889

7990
<build>

src/main/java/com/helper/JarClassLoader.java renamed to src/main/java/com/jar/JarClassLoader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.helper;
1+
package com.jar;
22

33
import java.io.IOException;
44
import java.lang.reflect.InvocationTargetException;

src/main/java/com/helper/JarRunner.java renamed to src/main/java/com/jar/JarRunner.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
package com.helper;
1+
package com.jar;
22

33
import java.io.IOException;
44
import java.net.MalformedURLException;
55
import java.net.URL;
66

7+
/**
8+
* 获取 main class:
9+
* 传参 file:///F:\source\scheduler\target\shadow.jar
10+
*/
711
public class JarRunner {
812

913
public static void main(String[] args) {

src/main/java/com/shadow/agent/DynamicAgent.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22

33
import com.shadow.core.asm.dynamic.AsmTransformer;
44
import com.shadow.core.asm.handler.*;
5-
import com.shadow.core.buddy.dynamic.BuddyTransformer;
65
import com.shadow.core.buddy.handler.AbstractBuddyHandler;
76
import com.shadow.core.buddy.handler.IBuddyHandler;
87
import com.shadow.core.javassist.dynamic.JavassistTransformer;
98
import com.shadow.core.javassist.handler.*;
109
import com.shadow.utils.CommonConstants;
1110
import com.shadow.utils.ParamResolveUtils;
1211
import jdk.internal.org.objectweb.asm.tree.MethodNode;
13-
import net.bytebuddy.ByteBuddy;
1412
import net.bytebuddy.agent.builder.AgentBuilder;
1513
import net.bytebuddy.agent.builder.ResettableClassFileTransformer;
1614

@@ -30,27 +28,27 @@ public static void agentmain(String agentArgs, Instrumentation inst) {
3028
if (resolveArgs.get(CommonConstants.ORIGIN_JOB_TYPE) != null &&
3129
resolveArgs.get(CommonConstants.CONTROLLER_CLASS) != null &&
3230
resolveArgs.get(CommonConstants.JOB_TYPE) != null) {
33-
CommonConstants.ScheduleTypeEnum originScheduleTypeEnum = CommonConstants.getByJobTypeName(resolveArgs.get(CommonConstants.ORIGIN_JOB_TYPE));
34-
CommonConstants.ScheduleTypeEnum scheduleTypeEnum = CommonConstants.getByJobTypeName(resolveArgs.get(CommonConstants.JOB_TYPE));
35-
if (originScheduleTypeEnum != null && scheduleTypeEnum != null) {
31+
CommonConstants.JobTypeEnum originJobTypeEnum = CommonConstants.getByJobTypeName(resolveArgs.get(CommonConstants.ORIGIN_JOB_TYPE));
32+
CommonConstants.JobTypeEnum jobTypeEnum = CommonConstants.getByJobTypeName(resolveArgs.get(CommonConstants.JOB_TYPE));
33+
if (originJobTypeEnum != null && jobTypeEnum != null) {
3634
// transformer
3735
ClassFileTransformer transformer = null;
3836
CommonConstants.ProxyTypeEnum proxyTypeEnum = CommonConstants.getByProxyTypeName(resolveArgs.get(CommonConstants.PROXY_TYPE));
3937
switch (proxyTypeEnum) {
4038
case ASM:
4139
// handle ASM default args
42-
MethodNode[] methodNodes = handleAsmDefaultArgs(resolveArgs, originScheduleTypeEnum, scheduleTypeEnum);
40+
MethodNode[] methodNodes = handleAsmDefaultArgs(resolveArgs, originJobTypeEnum, jobTypeEnum);
4341
transformer = new AsmTransformer(resolveArgs, methodNodes[0], methodNodes[1]);
4442
break;
4543
case BUDDY:
4644
// FIXME
47-
//AbstractBuddyHandler handler = handleBuddyDefaultArgs(resolveArgs, originScheduleTypeEnum, scheduleTypeEnum);
45+
//AbstractBuddyHandler handler = handleBuddyDefaultArgs(resolveArgs, originJobTypeEnum, jobTypeEnum);
4846
// transformer = new BuddyTransformer(resolveArgs).handle(handler, inst);
4947
break;
5048
case JAVASSIST:
5149
default:
5250
// handle Javassist default args
53-
handleJavassistDefaultArgs(resolveArgs, originScheduleTypeEnum, scheduleTypeEnum);
51+
handleJavassistDefaultArgs(resolveArgs, originJobTypeEnum, jobTypeEnum);
5452
transformer = new JavassistTransformer(resolveArgs);
5553
break;
5654
}
@@ -73,8 +71,8 @@ public static void agentmain(String agentArgs, Instrumentation inst) {
7371
}
7472

7573
private static MethodNode[] handleAsmDefaultArgs(Map<String, String> resolveArgs,
76-
CommonConstants.ScheduleTypeEnum originScheduleTypeEnum,
77-
CommonConstants.ScheduleTypeEnum scheduleTypeEnum) {
74+
CommonConstants.JobTypeEnum originJobTypeEnum,
75+
CommonConstants.JobTypeEnum jobTypeEnum) {
7876
// 1、common args
7977
handleCommonDefaultArgs(resolveArgs);
8078
// SPI
@@ -86,7 +84,7 @@ private static MethodNode[] handleAsmDefaultArgs(Map<String, String> resolveArgs
8684
handlerMap.put(handler.getClass().getSimpleName().replace(CommonConstants.ASM_HANDLER_NAME_SUFFIX, "").toUpperCase(), (AbstractAsmHandler) handler);
8785
}
8886
// 2、find origin handle for method name
89-
AbstractAsmHandler originHandler = handlerMap.get(originScheduleTypeEnum.name());
87+
AbstractAsmHandler originHandler = handlerMap.get(originJobTypeEnum.name());
9088
// if args not found method name, set default
9189
if (resolveArgs.get(CommonConstants.METHOD_NAME) == null) {
9290
resolveArgs.put(CommonConstants.METHOD_NAME, originHandler.getClass().getSimpleName().toLowerCase());
@@ -96,15 +94,15 @@ private static MethodNode[] handleAsmDefaultArgs(Map<String, String> resolveArgs
9694
// reset args for set CommonConstants.METHOD_NAME
9795
((AbstractAsmHandler) handler).setArgs(resolveArgs);
9896
}
99-
AbstractAsmHandler currentHandler = handlerMap.get(scheduleTypeEnum.name());
97+
AbstractAsmHandler currentHandler = handlerMap.get(jobTypeEnum.name());
10098
MethodNode runMethodNode = currentHandler.getAndSetClassMethod(CommonConstants.ASM_API_VERSION);
10199
MethodNode crudMethodNode = currentHandler.getAndSetCrudClassMethod(CommonConstants.ASM_API_VERSION);
102100
return new MethodNode[]{runMethodNode, crudMethodNode};
103101
}
104102

105103
private static AbstractBuddyHandler handleBuddyDefaultArgs(Map<String, String> resolveArgs,
106-
CommonConstants.ScheduleTypeEnum originScheduleTypeEnum,
107-
CommonConstants.ScheduleTypeEnum scheduleTypeEnum) {
104+
CommonConstants.JobTypeEnum originJobTypeEnum,
105+
CommonConstants.JobTypeEnum jobTypeEnum) {
108106
// 1、common args
109107
handleCommonDefaultArgs(resolveArgs);
110108
// SPI
@@ -116,7 +114,7 @@ private static AbstractBuddyHandler handleBuddyDefaultArgs(Map<String, String> r
116114
handlerMap.put(handler.getClass().getSimpleName().replace(CommonConstants.BYTEBUDDY_HANDLER_NAME_SUFFIX, "").toUpperCase(), (AbstractBuddyHandler) handler);
117115
}
118116
// 2、find origin handle for method name
119-
AbstractBuddyHandler originHandler = handlerMap.get(originScheduleTypeEnum.name());
117+
AbstractBuddyHandler originHandler = handlerMap.get(originJobTypeEnum.name());
120118
// if args not found method name, set default
121119
if (resolveArgs.get(CommonConstants.METHOD_NAME) == null) {
122120
resolveArgs.put(CommonConstants.METHOD_NAME, originHandler.getClass().getSimpleName().toLowerCase());
@@ -126,14 +124,14 @@ private static AbstractBuddyHandler handleBuddyDefaultArgs(Map<String, String> r
126124
// reset args for set CommonConstants.METHOD_NAME
127125
((AbstractBuddyHandler) handler).setArgs(resolveArgs);
128126
}
129-
AbstractBuddyHandler handler = handlerMap.get(scheduleTypeEnum.name());
127+
AbstractBuddyHandler handler = handlerMap.get(jobTypeEnum.name());
130128
handler.initOriginHandler(originHandler);
131129
return handler;
132130
}
133131

134132
private static void handleJavassistDefaultArgs(Map<String, String> resolveArgs,
135-
CommonConstants.ScheduleTypeEnum originScheduleTypeEnum,
136-
CommonConstants.ScheduleTypeEnum scheduleTypeEnum) {
133+
CommonConstants.JobTypeEnum originJobTypeEnum,
134+
CommonConstants.JobTypeEnum jobTypeEnum) {
137135
// 1、common args
138136
handleCommonDefaultArgs(resolveArgs);
139137
// SPI
@@ -144,7 +142,7 @@ private static void handleJavassistDefaultArgs(Map<String, String> resolveArgs,
144142
handlerMap.put(handler.getClass().getSimpleName().replace(CommonConstants.JAVASSIST_HANDLER_NAME_SUFFIX, "").toUpperCase(), (AbstractJavassistHandler) handler);
145143
}
146144
// 2、find origin handle for method name
147-
AbstractJavassistHandler originHandler = handlerMap.get(originScheduleTypeEnum.name());
145+
AbstractJavassistHandler originHandler = handlerMap.get(originJobTypeEnum.name());
148146
// if args not found method name, set default
149147
if (resolveArgs.get(CommonConstants.METHOD_NAME) == null) {
150148
resolveArgs.put(CommonConstants.METHOD_NAME, originHandler.getClass().getSimpleName().toLowerCase());
@@ -154,7 +152,7 @@ private static void handleJavassistDefaultArgs(Map<String, String> resolveArgs,
154152
// reset args for set CommonConstants.METHOD_NAME
155153
((AbstractJavassistHandler) handler).setArgs(resolveArgs);
156154
}
157-
AbstractJavassistHandler currentHandler = handlerMap.get(scheduleTypeEnum.name());
155+
AbstractJavassistHandler currentHandler = handlerMap.get(jobTypeEnum.name());
158156
resolveArgs.put(CommonConstants.METHOD_BODY, currentHandler.getMethodBody().get());
159157
}
160158
}

src/main/java/com/shadow/agent/LoadTimeAgent.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,24 @@ public static void premain(String agentArgs, Instrumentation inst) throws ClassN
2121
CommonUtils.printLogAllowed(resolveArgs);
2222
// 2、必要参数有时才处理
2323
if (resolveArgs.get(CommonConstants.JOB_TYPE) != null && resolveArgs.get(CommonConstants.CONTROLLER_CLASS) != null) {
24-
CommonConstants.ScheduleTypeEnum scheduleTypeEnum = CommonConstants.getByJobTypeName(resolveArgs.get(CommonConstants.JOB_TYPE));
25-
if (scheduleTypeEnum != null) {
24+
CommonConstants.JobTypeEnum jobTypeEnum = CommonConstants.getByJobTypeName(resolveArgs.get(CommonConstants.JOB_TYPE));
25+
if (jobTypeEnum != null) {
2626
// set default args
2727
handleCommonDefaultArgs(resolveArgs);
2828
// transformer
2929
ClassFileTransformer transformer = null;
30-
switch (CommonConstants.getByProxyTypeName(resolveArgs.get(CommonConstants.PROXY_TYPE))) {
30+
CommonConstants.ProxyTypeEnum proxyTypeEnum = CommonConstants.getByProxyTypeName(resolveArgs.get(CommonConstants.PROXY_TYPE));
31+
System.out.println("JOB TYPE: " + jobTypeEnum);
32+
System.out.println("PROXY TYPE: " + proxyTypeEnum);
33+
switch (proxyTypeEnum) {
3134
case ASM:
32-
transformer = new AsmTransformer(resolveArgs, scheduleTypeEnum);
35+
transformer = new AsmTransformer(resolveArgs);
3336
break;
3437
case BUDDY:
35-
new BuddyTransformer(resolveArgs, scheduleTypeEnum).handle(inst);
38+
new BuddyTransformer(resolveArgs).handle(inst);
3639
break;
3740
default:
38-
transformer = new JavassistTransformer(resolveArgs, scheduleTypeEnum);
41+
transformer = new JavassistTransformer(resolveArgs);
3942
break;
4043
}
4144
// add redefined transformer

src/main/java/com/shadow/core/AbstractHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
public abstract class AbstractHandler {
99

1010
/**
11-
* 记录 javaagent 传递的参数信息
11+
* agent request args
1212
*/
1313
private Map<String, String> args;
1414

@@ -47,7 +47,7 @@ public void setArgs(Map<String, String> args) {
4747
this.args = args;
4848
this.threadLocalFieldName = getArgs().get(CommonConstants.THREADLOCAL_FIELD_NAME);
4949
this.threadLocalClassName = getArgs().get(CommonConstants.THREADLOCAL_CLASS_NAME);
50-
this.threadLocalInnerClassName = this.threadLocalClassName == null ? null : this.threadLocalClassName.replaceAll(CommonConstants.DOT, CommonConstants.BIAS);
50+
this.threadLocalInnerClassName = this.threadLocalClassName == null ? null : this.threadLocalClassName.replaceAll(CommonConstants.REG_DOT, CommonConstants.BIAS);
5151
init();
5252
}
5353

src/main/java/com/shadow/core/AbstractTransformer.java

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,94 @@
11
package com.shadow.core;
22

3+
import com.shadow.core.common.ProxyClassLoader;
34
import com.shadow.utils.CommonConstants;
5+
import org.reflections.Reflections;
46

7+
import java.lang.reflect.Modifier;
58
import java.util.Map;
9+
import java.util.Set;
610

711
public abstract class AbstractTransformer {
812

913
/**
10-
* class name
14+
* current handle class name
15+
*/
16+
private String handlerClassName;
17+
18+
/**
19+
* current job type
20+
*/
21+
private CommonConstants.JobTypeEnum jobType;
22+
23+
/**
24+
* proxy controller class name
1125
* {@code java.lang.String}
1226
*/
1327
private String className;
1428

1529
/**
16-
* inner class name
30+
* proxy controller inner class name
1731
* {@code java/lang/String}
1832
*/
1933
private String innerClassName;
2034

2135
/**
22-
* 代理参数
36+
* agent request args
2337
*/
2438
private Map<String, String> args;
2539

26-
public String getClassName() {
27-
return className;
40+
protected CommonConstants.JobTypeEnum getJobType() {
41+
return jobType;
2842
}
2943

3044
public String getInnerClassName() {
3145
return innerClassName;
3246
}
3347

48+
public String getClassName() {
49+
return className;
50+
}
51+
3452
public Map<String, String> getArgs() {
3553
return args;
3654
}
3755

3856
public AbstractTransformer(Map<String, String> resolveArgs) {
3957
this.args = resolveArgs;
40-
this.className = getArgs().get(CommonConstants.CONTROLLER_CLASS);
41-
this.innerClassName = getClassName().replaceAll(CommonConstants.DOT, CommonConstants.BIAS);
58+
this.className = resolveArgs.get(CommonConstants.CONTROLLER_CLASS);
59+
this.innerClassName = this.className.replaceAll(CommonConstants.REG_DOT, CommonConstants.BIAS);
60+
this.jobType = CommonConstants.getByJobTypeName(resolveArgs.get(CommonConstants.JOB_TYPE));
61+
}
62+
63+
public AbstractTransformer(Map<String, String> resolveArgs, Class clazz) {
64+
this(resolveArgs);
65+
String clazzName = clazz.getName();
66+
Reflections reflections = new Reflections(clazzName, clazzName.substring(0, clazzName.lastIndexOf(CommonConstants.DOT)));
67+
Set<Class<?>> handlers = reflections.getSubTypesOf(clazz);
68+
for (Class<?> handler : handlers) {
69+
if (!Modifier.isAbstract(handler.getModifiers()) && handlerMatched(handler)) {
70+
handlerClassName = handler.getName();
71+
break;
72+
}
73+
}
74+
}
75+
76+
/**
77+
* match handler prefix
78+
*/
79+
protected abstract boolean handlerMatched(Class<?> handler);
80+
81+
protected AbstractHandler getHandler(ClassLoader loader) {
82+
try {
83+
ProxyClassLoader classLoader = new ProxyClassLoader(loader);
84+
Class<?> handlerClass = classLoader.loadClass(this.handlerClassName);
85+
AbstractHandler handler = (AbstractHandler) handlerClass.newInstance();
86+
handler.setArgs(getArgs());
87+
return handler;
88+
} catch (Exception e) {
89+
e.printStackTrace();
90+
}
91+
return null;
4292
}
4393

4494
/**

src/main/java/com/shadow/core/asm/dynamic/AsmTransformer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ public AsmTransformer(Map<String, String> resolveArgs, MethodNode runMethodNode,
2626
this.crudMethodNode = crudMethodNode;
2727
}
2828

29+
@Override
30+
protected boolean handlerMatched(Class<?> handler) {
31+
return getJobType().name().equalsIgnoreCase(handler.getSimpleName().replace(CommonConstants.ASM_HANDLER_NAME_SUFFIX, ""));
32+
}
33+
2934
@Override
3035
public byte[] transform(ClassLoader loader,
3136
String className,

src/main/java/com/shadow/core/asm/handler/AbstractAsmHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ String getInnerClassName() {
5151
}
5252

5353
public void initInnerClassName() {
54-
this.innerClassName = getArgs().get(CommonConstants.CONTROLLER_CLASS).replaceAll(CommonConstants.DOT, CommonConstants.BIAS);
54+
this.innerClassName = getArgs().get(CommonConstants.CONTROLLER_CLASS).replaceAll(CommonConstants.REG_DOT, CommonConstants.BIAS);
5555
}
5656

5757
public byte[] handle(byte[] classfileBuffer) {

src/main/java/com/shadow/core/asm/handler/SimpleJobAsmHandler.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import static jdk.internal.org.objectweb.asm.Opcodes.*;
44

55
import com.shadow.utils.*;
6-
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
76
import jdk.internal.org.objectweb.asm.Opcodes;
87
import jdk.internal.org.objectweb.asm.Type;
98
import jdk.internal.org.objectweb.asm.tree.*;

0 commit comments

Comments
 (0)