1. package com.deer.agent;
    2. import com.deer.agent.sandbox.AgentClazzTransformer;
    3. import java.lang.instrument.Instrumentation;
    4. import java.util.Arrays;
    5. public class AgentMain {
    6. public static void premain(String agentArgs, Instrumentation inst) {
    7. System.out.println("premain");
    8. }
    9. public static void agentmain(String agentArgs, Instrumentation inst){
    10. System.out.println("load agent...");
    11. Class[] clazzList = inst.getAllLoadedClasses();
    12. Arrays.stream(clazzList).forEach(clazz->{
    13. if(clazz.getName().startsWith("com.deer.base.service.impl")){
    14. //
    15. try {
    16. inst.addTransformer(new AgentClazzTransformer(), true);
    17. inst.retransformClasses(clazz);
    18. }catch (Exception e){
    19. //
    20. }
    21. }
    22. });
    23. }
    24. }
    1. package com.deer.agent.sandbox;
    2. import org.objectweb.asm.ClassReader;
    3. import org.objectweb.asm.ClassWriter;
    4. import java.lang.instrument.ClassFileTransformer;
    5. import java.lang.instrument.IllegalClassFormatException;
    6. import java.security.ProtectionDomain;
    7. public class AgentClazzTransformer implements ClassFileTransformer {
    8. @Override
    9. public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
    10. ClassReader cr = new ClassReader(classfileBuffer);
    11. ClassWriter cw = new ClassWriter(cr,ClassWriter.COMPUTE_MAXS);
    12. TraceClassVisitor traceClassVisitor = new TraceClassVisitor(cw);
    13. cr.accept(traceClassVisitor,ClassReader.EXPAND_FRAMES);
    14. return cw.toByteArray();
    15. }
    16. }
    1. package com.deer.agent.sandbox;
    2. import org.objectweb.asm.*;
    3. import org.objectweb.asm.commons.AdviceAdapter;
    4. public class TraceClassVisitor extends ClassVisitor implements Opcodes {
    5. private String clazzName;
    6. private String methodName;
    7. public TraceClassVisitor(ClassVisitor classVisitor) {
    8. super(ASM7, classVisitor);
    9. }
    10. private static int[] computeLvtSlotIndices(boolean isStatic, Type[] paramTypes) {
    11. int[] lvtIndex = new int[paramTypes.length];
    12. int nextIndex = isStatic ? 0 : 1;
    13. for (int i = 0; i < paramTypes.length; ++i) {
    14. lvtIndex[i] = nextIndex;
    15. if (isWideType(paramTypes[i])) {
    16. nextIndex += 2;
    17. } else {
    18. ++nextIndex;
    19. }
    20. }
    21. return lvtIndex;
    22. }
    23. private static boolean isWideType(Type aType) {
    24. return aType == Type.LONG_TYPE || aType == Type.DOUBLE_TYPE;
    25. }
    26. private static boolean isStatic(int access) {
    27. return (access & 8) > 0;
    28. }
    29. @Override
    30. public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
    31. super.visit(version, access, name, signature, superName, interfaces);
    32. clazzName = name;
    33. }
    34. @Override
    35. public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
    36. MethodVisitor mv = cv.visitMethod(access, name, descriptor, signature, exceptions);
    37. //跳过java原生相关的类
    38. if (!clazzName.startsWith("com/deer/base")) {
    39. return mv;
    40. }
    41. mv = new AdviceAdapter(ASM7, mv, access, name, descriptor) {
    42. private Type[] methodArgs;
    43. private String[] parameterNames;
    44. private int[] lvtSlotIndex;
    45. @Override
    46. protected void onMethodEnter() {
    47. //记录关键参数
    48. methodName = name;
    49. this.methodArgs = Type.getArgumentTypes(descriptor);
    50. this.parameterNames = new String[this.methodArgs.length];
    51. this.lvtSlotIndex =computeLvtSlotIndices(isStatic(access),this.methodArgs);
    52. super.onMethodEnter();
    53. }
    54. @Override
    55. protected void onMethodExit(int opcode) {
    56. if (methodName .equals("<init>") || methodName.equals("<clinit>")){
    57. return;
    58. }
    59. if (opcode == RETURN) {
    60. push((Type) null);
    61. } else if (opcode == LRETURN || opcode == DRETURN) {
    62. dup2();
    63. box(Type.getReturnType(methodDesc));
    64. } else {
    65. dup();
    66. box(Type.getReturnType(methodDesc));
    67. }
    68. Type objectType = Type.getObjectType("java/lang/Object");
    69. push(lvtSlotIndex.length);
    70. newArray(objectType);
    71. for (int j = 0; j < lvtSlotIndex.length; j++) {
    72. int index = lvtSlotIndex[j];
    73. Type type = methodArgs[j];
    74. dup();
    75. push(j);
    76. mv.visitVarInsn(ALOAD, index);
    77. box(type);
    78. arrayStore(objectType);
    79. }
    80. visitLdcInsn(clazzName);
    81. visitLdcInsn(methodName);
    82. mv.visitMethodInsn(INVOKESTATIC, "com/deer/agent/sandbox/Sender", "send", "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V", false);
    83. }
    84. @Override
    85. public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
    86. for (int i=0;i<this.lvtSlotIndex.length;i++){
    87. if(this.lvtSlotIndex[i] == index){
    88. this.parameterNames[i]=name;
    89. }
    90. }
    91. }
    92. };
    93. return mv;
    94. }
    95. }