ASM

  • ASM
  • ASM获取方法参数名字
  • ASM增强代理类,并覆写方法
    • ASM工厂类`
    • Class的适配器类(ClassAdapter )`
    • [代理类
      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
      137
      138
      139
      140
      141
      142
      	- [生成的class`](#%E7%94%9F%E6%88%90%E7%9A%84class)

      <!-- /TOC -->

      # ASM
      ASM是一个Java字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM可以直接产生二进制class文件,也可以在类被加载入Java虚拟机之前动态改变类行为。
      ASM实现可以是接口,也是可以类。
      Java class被存储在严格格式定义的`.class`文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及Java字节码(指令)。ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
      ## JVM执行class的指令
      在Java中每一个方法在执行的时候JVM都会为其分配一个"帧",帧是用来存储方法中计算所需要的所有数据。其中第0个元素就是`this`,如果方法有参数传入会排在它的后面。
      ### ALOAD_0
      这个指令是`LOAD`系列指令中的一个,它的意思表示装载当前第0个元素到堆栈中。代码上相当于"this"。而这个数据元素的类型是一个引用类型。这些指令包含`ALOAD`,`ILOAD`,`LLOAD`,`FLOAD`,`DLOAD`。区分它们的作用就是针对不用数据类型而准备的`LOAD`指令,此外还有专门负责处理数组的指令`SALOAD`。
      ### Invokespecial
      这个指令是调用系列指令中的一个。其目的是调用对象类的方法。后面需要给上父类的方法完整签名。"#8"的意思是 `.class`文件常量表中第8个元素。值为`java/lang/Object."<init>":()V`。结合`ALOAD_0`。这两个指令可以翻译为`super()`。其含义是调用自己的父类构造方法。
      ### GETSTATIC
      这个指令是`GET`系列指令中的一个其作用是获取静态字段内容到堆栈中。这一系列指令包括了:`GETFIELD`、`GETSTATIC`。它们分别用于获取动态字段和静态字段。
      ### IDC
      这个指令的功能是从常量表中装载一个数据到堆栈中。
      ### Invokevirtual
      是一种调用指令,这个指令区别与`invokespecial`的是它是根据引用调用对象类的方法。这里有一篇文章专门讲解这两个指令:"http://wensiqun.iteye.com/blog/1125503"。
      ### RETURN
      这也是一系列指令中的一个,其目的是方法调用完毕返回,可用的其他指令有:`IRETURN`,`DRETURN`,`ARETURN`等,用于表示不同类型参数的返回。
      <!-- more -->
      # ASM获取方法参数名字
      ## ASM
      ```` java
      package asm;

      import java.io.IOException;
      import java.lang.reflect.Method;
      import java.lang.reflect.Modifier;

      import org.objectweb.asm.ClassReader;
      import org.objectweb.asm.ClassVisitor;
      import org.objectweb.asm.ClassWriter;
      import org.objectweb.asm.Label;
      import org.objectweb.asm.MethodVisitor;
      import org.objectweb.asm.Opcodes;
      import org.objectweb.asm.Type;

      import com.me.WorkServiceImpl;

      /**
      * <p>
      * 基于asm的工具类
      * </p>
      */
      public final class ASM {

      private ASM() {
      }

      /**
      *
      * <p>
      * 比较参数类型是否一致
      * </p>
      *
      * @param types
      * asm的类型({@link Type})
      * @param clazzes
      * java 类型({@link Class})
      * @return
      */
      private static boolean sameType(Type[] types, Class<?>[] clazzes) {
      // 个数不同
      if (types.length != clazzes.length) {
      return false;
      }
      for (int i = 0; i < types.length; i++) {
      if (!Type.getType(clazzes[i]).equals(types[i])) {
      return false;
      }
      }
      return true;
      }

      /**
      *
      * <p>
      * 获取方法的参数名
      * </p>
      *
      * @param m
      * @return
      */
      public static String[] getMethodParamNames(final Method method) {
      //参数名字
      final String[] paramNames = new String[method.getParameterTypes().length];
      //方法名字
      final String methodName = method.getDeclaringClass().getName();
      //class写入
      final ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
      ClassReader classReader = null;
      try {
      //写入方法
      classReader = new ClassReader(methodName);
      } catch (IOException e) {
      e.printStackTrace();
      }
      classReader.accept(new ClassVisitor(Opcodes.ASM4, classWriter) {
      @Override
      public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
      //参数类型
      final Type[] args = Type.getArgumentTypes(desc);
      // 判断方法名字,方法参数
      if (!name.equals(method.getName()) || !sameType(args, method.getParameterTypes())) {
      return super.visitMethod(access, name, desc, signature, exceptions);
      }
      //方法访问
      MethodVisitor methodVisitor = cv.visitMethod(access, name, desc, signature, exceptions);
      return new MethodVisitor(Opcodes.ASM4, methodVisitor) {
      @Override
      public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
      int i = index - 1;
      // 如果是静态方法,则第一就是参数
      // 如果不是静态方法,则第一个是"this",然后才是方法的参数
      if (Modifier.isStatic(method.getModifiers())) {
      i = index;
      }
      if (i >= 0 && i < paramNames.length) {
      paramNames[i] = name;
      }
      super.visitLocalVariable(name, desc, signature, start, end, index);
      }
      };
      }
      }, 0);
      return paramNames;
      }

      //ASM支持泛型
      public static void main(String[] args) throws SecurityException, NoSuchMethodException {
      //获取方法参数,方法名字,方法参数
      String[] s = getMethodParamNames(WorkServiceImpl.class.getMethod("work", String.class,Object.class));
      for (int i = 0; i < s.length; i++) {
      System.out.println(s[i]);
      }
      }

      }
      `

MethodParamNamesScanner

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package asm;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodNode;

import com.me.WorkServiceImpl;


/**
* 获取方法参数名字
*/
public class MethodParamNamesScanner {

/**
* 获取方法参数名列表
*
* @param clazz
* @param m
* @return
* @throws IOException
*/
public static List<String> getMethodParamNames(Class<?> clazz, Method method) throws IOException {
try (InputStream in = clazz.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class")) {
return getMethodParamNames(in, method);
}
}

public static List<String> getMethodParamNames(InputStream in, Method method) throws IOException {
try (InputStream ins = in) {
return getParamNames(ins, new EnclosingMetadata(method.getName(), Type.getMethodDescriptor(method),
method.getParameterTypes().length));
}
}

/**
* 获取构造器参数名列表
*
* @param clazz
* @param constructor
* @return
*/
public static List<String> getConstructorParamNames(Class<?> clazz, Constructor<?> constructor) {
try (InputStream in = clazz.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class")) {
return getConstructorParamNames(in, constructor);
} catch (IOException e) {
e.printStackTrace();
}
return new ArrayList<String>();
}

public static List<String> getConstructorParamNames(InputStream ins, Constructor<?> constructor) {
try (InputStream in = ins) {
return getParamNames(
in,
new EnclosingMetadata(constructor.getName(), Type.getConstructorDescriptor(constructor), constructor
.getParameterTypes().length));
} catch (IOException e1) {
e1.printStackTrace();
}
return new ArrayList<String>();
}

/**
* 获取参数名列表辅助方法
*
* @param in
* @param m
* @return
* @throws IOException
*/
private static List<String> getParamNames(InputStream in, EnclosingMetadata enclosingMetadata) throws IOException {
ClassReader classReader = new ClassReader(in);
ClassNode classNode = new ClassNode();
classReader.accept(classNode, ClassReader.EXPAND_FRAMES);// 建议EXPAND_FRAMES
// ASM树接口形式访问
List<MethodNode> methods = classNode.methods;
List<String> list = new ArrayList<String>();
for (int i = 0; i < methods.size(); ++i) {
List<LocalVariable> varNames = new ArrayList<LocalVariable>();
MethodNode methodNode = methods.get(i);
// 验证方法签名
if (methodNode.desc.equals(enclosingMetadata.desc) && methodNode.name.equals(enclosingMetadata.name)) {
List<LocalVariableNode> local_variables = methodNode.localVariables;
for (int k = 0; k < local_variables.size(); k++) {
String varName = local_variables.get(k).name;
// index-记录了正确的方法本地变量索引。(方法本地变量顺序可能会被打乱。而index记录了原始的顺序)
int index = local_variables.get(k).index;
// 非静态方法,第一个参数是this
if (!"this".equals(varName)) {
varNames.add(new LocalVariable(index, varName));
}
}
LocalVariable[] tmpArr = varNames.toArray(new LocalVariable[varNames.size()]);
// 根据index来重排序,以确保正确的顺序
Arrays.sort(tmpArr);
for (int j = 0; j < enclosingMetadata.size; j++) {
list.add(tmpArr[j].name);
}
break;
}
}
return list;
}

/**
* 方法本地变量索引和参数名封装
*
* @author xby Administrator
*/
static class LocalVariable implements Comparable<LocalVariable> {
public int index;
public String name;

public LocalVariable(int index, String name) {
this.index = index;
this.name = name;
}

public int compareTo(LocalVariable o) {
return this.index - o.index;
}
}

/**
* 封装方法描述和参数个数
*
* @author xby Administrator
*/
static class EnclosingMetadata {
// method name
public String name;
// method description
public String desc;
// params size
public int size;

public EnclosingMetadata(String name, String desc, int size) {
this.name = name;
this.desc = desc;
this.size = size;
}
}

public static void main(String[] args) throws IOException {
for (Method m : WorkServiceImpl.class.getDeclaredMethods()) {
List<String> list = getMethodParamNames(WorkServiceImpl.class, m);
System.out.println(m.getName() + ":");
for (String str : list) {
System.out.println(str);
}
System.out.println("------------------------");
}
}
}

ASM增强代理类,并覆写方法

  1. 生成被代理类的子类,并重写所有方法(除java.lang.Object类定义的方法),增加beforeafter拦截。
  2. 重新定义被代理类的所有属性(不包括属性的赋值)。
  3. 把生成的class文件保存到硬盘中。
  4. 从内存中加载新生成的class。

    ASM工厂类

    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
    package asm;

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;

    import org.objectweb.asm.ClassReader;
    import org.objectweb.asm.ClassVisitor;
    import org.objectweb.asm.ClassWriter;

    /**
    *
    * <p>
    * asm 代理工厂
    * </p>
    */
    public class AsmFactory {
    public static final String SUFIX = "$EnhancedByCc";
    public static BytecodeLoader classLoader = new BytecodeLoader();

    /**
    *
    * <p>
    * 根据字节码加载class
    * </p>
    */
    public static class BytecodeLoader extends ClassLoader {
    public Class<?> defineClass(String className, byte[] byteCodes) {
    return super.defineClass(className, byteCodes, 0, byteCodes.length);
    }
    }

    /**
    *
    * <p>
    * 返回代理类(增强类)
    * </p>
    *
    * @param <T>
    * @param clazz
    * @return
    * @throws Exception
    */
    @SuppressWarnings("unchecked")
    protected static <T> Class<T> getEnhancedClass(Class<T> clazz) {
    String enhancedClassName = clazz.getName() + SUFIX;
    try {
    return (Class<T>) classLoader.loadClass(enhancedClassName);
    } catch (ClassNotFoundException classNotFoundException) {//class没有找到,重新加载class
    ClassReader reader = null;
    try {
    reader = new ClassReader(clazz.getName());
    } catch (IOException ioexception) {
    throw new RuntimeException(ioexception);
    }
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    //初始化classvisitor
    ClassVisitor visitor = new ClassAdapter(enhancedClassName, clazz, writer);
    reader.accept(visitor, 0);
    byte[] byteCodes = writer.toByteArray();
    //写入class文件
    writeClazz(enhancedClassName, byteCodes);
    Class<T> result = (Class<T>) classLoader.defineClass(enhancedClassName, byteCodes);
    return result;
    }
    }

    /**
    *
    * <p>
    * 把java字节码写入class文件
    * </p>
    *
    * @param <T>
    * @param name
    * @param data
    * @throws FileNotFoundException
    * @throws IOException
    */
    public static <T> void writeClazz(String name, byte[] data) {
    try {
    File file = new File("C:/TEMP/" + name + ".class");
    FileOutputStream fout = new FileOutputStream(file);
    fout.write(data);
    fout.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    Class<RoleService> rsCls = getEnhancedClass(RoleService.class);
    rsCls.newInstance().executeOuter(1);
    }

    }

Class的适配器类(ClassAdapter )

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
package asm;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/**
*
* <p>根据class A生成一个class B extends A</p>
* <li>重写A及A父类的所有方法,eg. public void xx() {super.xx();}
* <li>copy A类定义的所有属性
*
1、生成被代理类的子类,并重写所有方法(除java.lang.Object类定义的方法),增加before和after拦截。
2、重新定义被代理类的所有属性(不包括属性的赋值)。
3、把生成的class文件保存到硬盘中。
4、从内存中加载新生成的class。
*
*/
public class ClassAdapter extends ClassVisitor implements Opcodes{
public static final String INIT = "<init>";
private ClassWriter classWriter;
//原始类名字
private String originalClassName;
//增强类名字
private String enhancedClassName;
//原始类
private Class<?> originalClass;


/**
*
* <p>Title: </p>
* <p>Description: </p>
* @param enhancedClassName 增强类
* @param targetClass 目标类
* @param writer class写入
*/
public ClassAdapter(String enhancedClassName, Class<?> targetClass, ClassWriter writer) {
super(Opcodes.ASM4, writer);
this.classWriter = writer;
this.originalClassName = targetClass.getName();
this.enhancedClassName = enhancedClassName;
this.originalClass = targetClass;
}

@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
cv.visit(version, Opcodes.ACC_PUBLIC, toAsmCls(enhancedClassName), signature, name, interfaces);
}

/**
* 访问属性
*/
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
// 拷贝所有属性 可使用java反射给属性赋值(生成class后newInstance在赋值)
return super.visitField(access, name, desc, signature, value);
}

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
// 删除所有方法
return null;
}

/**
* 把类名中的.替换为/
*
* @param className
* @return
*/
private static String toAsmCls(String className) {
return className.replace('.', '/');
}

/**
*
* <p>
* 前置方法
* </p>
*
* @see TxHandler
* @param mWriter
*/
private static void doBefore(MethodVisitor mWriter, String methodInfo) {
mWriter.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mWriter.visitLdcInsn("before method : " + methodInfo);
mWriter.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
// 或者直接调用静态方法
// mWriter.visitLdcInsn(methodInfo);
// mWriter.visitMethodInsn(INVOKESTATIC,toAsmCls(TxHandler.class.getName()),"before","(Ljava/lang/String;)V");
}

/**
*
* <p>
* 后置方法
* </p>
*
* @see TxHandler
* @param mWriter
*/
private static void doAfter(MethodVisitor mWriter, String methodInfo) {
mWriter.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mWriter.visitLdcInsn("after method : " + methodInfo);
mWriter.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
}

/**
* 判断方法是否可以重新覆写
* <p>
* object类本身的方法不做重写
* </p>
* <p>
* "main" 方法不做重写
* </p>
*
* @param m
* @return
*/
public static boolean needOverride(Method method) {
// object类本身的方法不做重写
if (method.getDeclaringClass().getName().equals(Object.class.getName())) {
return false;
}
// "main" 方法不做重写
if (Modifier.isPublic(method.getModifiers()) && Modifier.isStatic(method.getModifiers()) && method.getReturnType().getName().equals("void")
&& method.getName().equals("main")) {
return false;
}
return true;
}

@Override
public void visitEnd() {
// 如果originalClass定义了私有成员变量,那么直接在visitMethod中复制originalClass的<init>会报错。
// ALOAD 0
// INVOKESPECIAL cc/RoleService.<init>()V
// RETURN
// // 调用originalClassName的<init>方法,否则class不能实例化
MethodVisitor mvInit = classWriter.visitMethod(ACC_PUBLIC, INIT, "()V", null, null);
mvInit.visitVarInsn(ALOAD, 0);
mvInit.visitMethodInsn(INVOKESPECIAL, toAsmCls(originalClassName), INIT, "()V");
mvInit.visitInsn(RETURN);
mvInit.visitMaxs(0, 0);
mvInit.visitEnd();

// 获取所有方法,并重写(main方法 和 Object的方法除外)
Method[] methods = originalClass.getMethods();
for (Method m : methods) {
//不覆写main方法
if (!needOverride(m)) {
continue;
}
//类型
Type mt = Type.getType(m);
StringBuilder methodInfo = new StringBuilder(originalClassName);
methodInfo.append(".").append(m.getName());
methodInfo.append("|");

Class<?>[] paramTypes = m.getParameterTypes();
//类型名字
for (Class<?> t : paramTypes) {
methodInfo.append(t.getName()).append(",");
}
if (paramTypes.length > 0) {
//删除最后一个“,”
methodInfo.deleteCharAt(methodInfo.length() - 1);
}

// 方法是被哪个类定义的
String declaringCls = toAsmCls(m.getDeclaringClass().getName());
// 方法 description
MethodVisitor mWriter = classWriter.visitMethod(ACC_PUBLIC, m.getName(), mt.toString(), null, null);
// insert code here (before)
doBefore(mWriter, methodInfo.toString());
int i = 0;
// 如果不是静态方法 load this对象
if (!Modifier.isStatic(m.getModifiers())) {
mWriter.visitVarInsn(ALOAD, i++);
}
StringBuilder sb = new StringBuilder(m.getName());
// load 出方法的所有参数
for (Class<?> tCls : m.getParameterTypes()) {
Type t = Type.getType(tCls);
sb.append(loadCode(t)).append(",");
mWriter.visitVarInsn(loadCode(t), i++);
if (t.getSort() == Type.LONG || t.getSort() == Type.DOUBLE) {
i++;
}
}
// super.xxx();
mWriter.visitMethodInsn(INVOKESPECIAL, declaringCls, m.getName(), mt.toString());
// 处理返回值类型
Type rt = Type.getReturnType(m);
// 没有返回值
if (rt.toString().equals("V")) {
doAfter(mWriter, methodInfo.toString());
mWriter.visitInsn(RETURN);
}
// 把return xxx() 转变成 : Object o = xxx(); return o;
else {
int storeCode = storeCode(rt);
int loadCode = loadCode(rt);
int returnCode = rtCode(rt);
mWriter.visitVarInsn(storeCode, i);
doAfter(mWriter, methodInfo.toString());
mWriter.visitVarInsn(loadCode, i);
mWriter.visitInsn(returnCode);
}
// 已设置了自动计算,但还是要调用一下,不然会报错
mWriter.visitMaxs(i, ++i);
mWriter.visitEnd();
}
cv.visitEnd();
}

/**
*
* <p>
* get StoreCode(Opcodes#xStore)
* </p>
*
*
* @param type
* @return
*/
public static int storeCode(Type type) {
//排序
int sort = type.getSort();
switch (sort) {
case Type.ARRAY:
sort = ASTORE;
break;
case Type.BOOLEAN:
sort = ISTORE;
break;
case Type.BYTE:
sort = ISTORE;
break;
case Type.CHAR:
sort = ISTORE;
break;
case Type.DOUBLE:
sort = DSTORE;
break;
case Type.FLOAT:
sort = FSTORE;
break;
case Type.INT:
sort = ISTORE;
break;
case Type.LONG:
sort = LSTORE;
break;
case Type.OBJECT:
sort = ASTORE;
break;
case Type.SHORT:
sort = ISTORE;
break;
default:
break;
}
return sort;
}

/**
*
* <p>
* get StoreCode(Opcodes#xLOAD)
* </p>
*
* @param type
* @return
*/
public static int loadCode(Type type) {
int sort = type.getSort();
switch (sort) {
case Type.ARRAY:
sort = ALOAD;
break;
case Type.BOOLEAN:
sort = ILOAD;
break;
case Type.BYTE:
sort = ILOAD;
break;
case Type.CHAR:
sort = ILOAD;
break;
case Type.DOUBLE:
sort = DLOAD;
break;
case Type.FLOAT:
sort = FLOAD;
break;
case Type.INT:
sort = ILOAD;
break;
case Type.LONG:
sort = LLOAD;
break;
case Type.OBJECT:
sort = ALOAD;
break;
case Type.SHORT:
sort = ILOAD;
break;
default:
break;
}
return sort;
}

/**
*
* <p>
* get StoreCode(Opcodes#xRETURN)
* </p>
*
* @param type
* @return
*/
public static int rtCode(Type type) {
int sort = type.getSort();
switch (sort) {
case Type.ARRAY:
sort = ARETURN;
break;
case Type.BOOLEAN:
sort = IRETURN;
break;
case Type.BYTE:
sort = IRETURN;
break;
case Type.CHAR:
sort = IRETURN;
break;
case Type.DOUBLE:
sort = DRETURN;
break;
case Type.FLOAT:
sort = FRETURN;
break;
case Type.INT:
sort = IRETURN;
break;
case Type.LONG:
sort = LRETURN;
break;
case Type.OBJECT:
sort = ARETURN;
break;
case Type.SHORT:
sort = IRETURN;
break;
default:
break;
}
return sort;
}
}

代理类

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
package asm;


/**
* <p></p>
*/
public class RoleService extends Service{
private String field1 = "";

public String executeOuter(Integer name) {
System.out.println("executeOuter call super.query()");
return query();
}

@Override
public String query() {
System.out.println("execute (RoleService): query");
return "query result (RoleService)";
}

public String getField1() {
return field1;
}

public void setField1(String field1) {
this.field1 = field1;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Service.java 11:59:38 AM Apr 27, 2012
*
* Copyright(c) 2000-2012 HC360.COM, All Rights Reserved.
*/
package asm;


/**
* <p></p>
*
*/
public class Service extends Dao{

@Override
public void insert(Object o) {
super.insert(o);
}

}
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
/**
* Dao.java 11:58:24 AM Apr 27, 2012
*
* Copyright(c) 2000-2012 HC360.COM, All Rights Reserved.
*/
package asm;
/**
* <p></p>
*
*/
public class Dao {
public void insert(Object o) {
System.out.println("insert : " + o);
}

public String query() {
System.out.println("execute (Dao): query");
return "query result (Dao)";
}
public String query2() {
System.out.println("execute (Dao): query2");
return "query2 result (Dao)";
}

public int test() {
System.out.println("execute (Dao) : test");
return 0;
}

protected void testProtected() {
System.out.println("execute (Dao) : testProtected");
testPrivate();
}

private void testPrivate() {
System.out.println("execute (Dao) : testPrivate");
}

public Dao[] testArray(String[] s,Object o) {
System.out.println("execute (Dao) : testArray");
return null;
}
}

生成的class

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
package asm;

import java.io.PrintStream;

public class RoleService$EnhancedByCc extends RoleService
{
private String field1;

public String executeOuter(Integer paramInteger)
{
System.out.println("before method : asm.RoleService.executeOuter|java.lang.Integer");
String str = super.executeOuter(paramInteger);
System.out.println("after method : asm.RoleService.executeOuter|java.lang.Integer");
return str;
}

public String query()
{
System.out.println("before method : asm.RoleService.query|");
String str = super.query();
System.out.println("after method : asm.RoleService.query|");
return str;
}

public void setField1(String paramString)
{
System.out.println("before method : asm.RoleService.setField1|java.lang.String");
super.setField1(paramString);
System.out.println("after method : asm.RoleService.setField1|java.lang.String");
}

public String getField1()
{
System.out.println("before method : asm.RoleService.getField1|");
String str = super.getField1();
System.out.println("after method : asm.RoleService.getField1|");
return str;
}

public void insert(Object paramObject)
{
System.out.println("before method : asm.RoleService.insert|java.lang.Object");
super.insert(paramObject);
System.out.println("after method : asm.RoleService.insert|java.lang.Object");
}

public String query2()
{
System.out.println("before method : asm.RoleService.query2|");
String str = super.query2();
System.out.println("after method : asm.RoleService.query2|");
return str;
}

public int test()
{
System.out.println("before method : asm.RoleService.test|");
int i = super.test();
System.out.println("after method : asm.RoleService.test|");
return i;
}

public Dao[] testArray(String[] paramArrayOfString, Object paramObject)
{
System.out.println("before method : asm.RoleService.testArray|[Ljava.lang.String;,java.lang.Object");
Dao[] arrayOfDao = super.testArray(paramArrayOfString, paramObject);
System.out.println("after method : asm.RoleService.testArray|[Ljava.lang.String;,java.lang.Object");
return arrayOfDao;
}
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×