• Skywalking流程分析_7(构造/实例方法的增强流程)


    前言

    this.enhance

    protected DynamicType.Builder<?> enhance(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder,
                                             ClassLoader classLoader, EnhanceContext context) throws PluginException {
        //静态方法的增强
        newClassBuilder = this.enhanceClass(typeDescription, newClassBuilder, classLoader);
        //构造、实例方法的增强
        newClassBuilder = this.enhanceInstance(typeDescription, newClassBuilder, classLoader, context);
    
        return newClassBuilder;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在上文中我们分析的静态方法的增强是如何做的,接下来我们来分析构造和实例方法

    ClassEnhancePluginDefine.enhanceInstance(typeDescription, newClassBuilder, classLoader, context)

    protected DynamicType.Builder<?> enhanceInstance(TypeDescription typeDescription,
        DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
        EnhanceContext context) throws PluginException {
        //查找构造方法的切点
        ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints();
        //查找实例方法的切点
        InstanceMethodsInterceptPoint[] instanceMethodsInterceptPoints = getInstanceMethodsInterceptPoints();
        String enhanceOriginClassName = typeDescription.getTypeName();
        boolean existedConstructorInterceptPoint = false;
        if (constructorInterceptPoints != null && constructorInterceptPoints.length > 0) {
            existedConstructorInterceptPoint = true;
        }
        boolean existedMethodsInterceptPoints = false;
        if (instanceMethodsInterceptPoints != null && instanceMethodsInterceptPoints.length > 0) {
            existedMethodsInterceptPoints = true;
        }
    
        /**
         * nothing need to be enhanced in class instance, maybe need enhance static methods.
         * 没有要增强的那么直接返回
         */
        if (!existedConstructorInterceptPoint && !existedMethodsInterceptPoints) {
            return newClassBuilder;
        }
    
        /**
         * Manipulate class source code.
    * * new class need:
    * 1.Add field, name {@link #CONTEXT_ATTR_NAME}. * 2.Add a field accessor for this field. * * And make sure the source codes manipulation only occurs once. * */
    // 如果被拦截的类没有实现EnhancedInstance接口 if (!typeDescription.isAssignableTo(EnhancedInstance.class)) { if (!context.isObjectExtended()) { //给要增强的类添加_$EnhancedClassField_ws字段, //并实现了EnhancedInstance接口的set/get方法,来获取这个字段 //新增这个字段的作用是可以放置自己的数据,然后通过这两个set/get方法来存放和拿取 newClassBuilder = newClassBuilder.defineField( CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE) .implement(EnhancedInstance.class) .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME)); // 将记录状态EnhanceContext标识符设置为已新增新的字段或者实现新的接口 context.extendObjectCompleted(); } } /** * 2. enhance constructors * 构造器增强逻辑 */ if (existedConstructorInterceptPoint) { //获取所有构造方法的切点 for (ConstructorInterceptPoint constructorInterceptPoint : constructorInterceptPoints) { //要增加的类是Bootstrap类加载器加载的 if (isBootstrapInstrumentation()) { newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()) .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration() .to(BootstrapInstrumentBoost .forInternalDelegateClass(constructorInterceptPoint .getConstructorInterceptor())))); } else { newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()) .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration() .to(new ConstructorInter(constructorInterceptPoint .getConstructorInterceptor(), classLoader)))); } } } /** * 3. enhance instance methods * 实例方法增强逻辑 */ if (existedMethodsInterceptPoints) { //获取所有实例方法的切点 for (InstanceMethodsInterceptPoint instanceMethodsInterceptPoint : instanceMethodsInterceptPoints) { String interceptor = instanceMethodsInterceptPoint.getMethodsInterceptor(); if (StringUtil.isEmpty(interceptor)) { throw new EnhanceException("no InstanceMethodsAroundInterceptor define to enhance class " + enhanceOriginClassName); } ElementMatcher.Junction<MethodDescription> junction = not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher()); if (instanceMethodsInterceptPoint instanceof DeclaredInstanceMethodsInterceptPoint) { junction = junction.and(ElementMatchers.<MethodDescription>isDeclaredBy(typeDescription)); } if (instanceMethodsInterceptPoint.isOverrideArgs()) { //要增加的类是Bootstrap类加载器加载的 if (isBootstrapInstrumentation()) { newClassBuilder = newClassBuilder.method(junction) .intercept(MethodDelegation.withDefaultConfiguration() .withBinders(Morph.Binder.install(OverrideCallable.class)) .to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor))); } else { newClassBuilder = newClassBuilder.method(junction) .intercept(MethodDelegation.withDefaultConfiguration() .withBinders(Morph.Binder.install(OverrideCallable.class)) .to(new InstMethodsInterWithOverrideArgs(interceptor, classLoader))); } } else { //要增加的类是Bootstrap类加载器加载的 if (isBootstrapInstrumentation()) { newClassBuilder = newClassBuilder.method(junction) .intercept(MethodDelegation.withDefaultConfiguration() .to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor))); } else { newClassBuilder = newClassBuilder.method(junction) .intercept(MethodDelegation.withDefaultConfiguration() .to(new InstMethodsInter(interceptor, classLoader))); } } } } return newClassBuilder; }
    • 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

    总结

    • 给要增强的类添加_$EnhancedClassField_ws字段,并实现了EnhancedInstance接口的set/get方法,来获取这个字段。新增这个字段的作用是可以放置自己的数据,然后通过这两个set/get方法来存放和拿取
    • 执行构造器增强逻辑
    • 执行实例方法增强逻辑

    下面我们来逐步分析构造器增强和实例方法增强

    构造器增强

    非JDK的类库是被ConstructorInter所增强的

    newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher())
                         .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration()
                                                             .to(new ConstructorInter(constructorInterceptPoint
                                                                 .getConstructorInterceptor(), classLoader))));
    
    • 1
    • 2
    • 3
    • 4
    ConstructorInter
    public class ConstructorInter {
        private static final ILog LOGGER = LogManager.getLogger(ConstructorInter.class);
    
        private InstanceConstructorInterceptor interceptor;
    
        /**
         * @param constructorInterceptorClassName class full name.
         */
        public ConstructorInter(String constructorInterceptorClassName, ClassLoader classLoader) throws PluginException {
            try {
                // 实例化自定义的拦截器
                //对于同一份字节码,如果由不同的类加载器进行加载,那么加载出来的两个实例不相同
                interceptor = InterceptorInstanceLoader.load(constructorInterceptorClassName, classLoader);
            } catch (Throwable t) {
                throw new PluginException("Can't create InstanceConstructorInterceptorV2.", t);
            }
        }
    
        /**
         * Intercept the target constructor.
         *
         * @param obj          target class instance.
         * @param allArguments all constructor arguments
         */
        @RuntimeType
        public void intercept(@This Object obj, @AllArguments Object[] allArguments) {
            try {
                //这里向上转型为EnhancedInstance的原因是为了使用之前新添加的_$EnhancedClassField_ws字段
                //使用setSkyWalkingDynamicField/getSkyWalkingDynamicField方法来存放和获取自己的数据
                EnhancedInstance targetObject = (EnhancedInstance) obj;
                //在原来的构造方法执行完后,再执行
                interceptor.onConstruct(targetObject, allArguments);
            } catch (Throwable t) {
                LOGGER.error("ConstructorInter failure.", t);
            }
    
        }
    }
    
    • 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

    ConstructorInter逻辑总结

    • 构造方法中实例化自定义的拦截器
    • 在原先的构造方法执行完,再执行interceptor.onConstruct(targetObject, allArguments)

    kafka为例

    public class KafkaProducerInstrumentation extends AbstractKafkaInstrumentation {
    
        public static final String ENHANCE_CLASS = "org.apache.kafka.clients.producer.KafkaProducer";
        public static final String CONSTRUCTOR_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.kafka.ProducerConstructorInterceptor";
        public static final String CONSTRUCTOR_INTERCEPTOR_FLAG = "org.apache.kafka.clients.producer.ProducerConfig";
    
        @Override
        public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
            return new ConstructorInterceptPoint[] {
                new ConstructorInterceptPoint() {
                    @Override
                    public ElementMatcher<MethodDescription> getConstructorMatcher() {
                        return takesArgumentWithType(0, CONSTRUCTOR_INTERCEPTOR_FLAG);
                    }
    
                    @Override
                    public String getConstructorInterceptor() {
                        return CONSTRUCTOR_INTERCEPTOR_CLASS;
                    }
                }
            };
        }
    
        @Override
        protected ClassMatch enhanceClass() {
            return byName(ENHANCE_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
    • 这里拦截的是org.apache.kafka.clients.producer.KafkaProducer类的构造方法
    • 拦截具体的构造方法是第一个参数类型为org.apache.kafka.clients.producer.ProducerConfig
    • 拦截的执行类是org.apache.skywalking.apm.plugin.kafka.ProducerConstructorInterceptor
    public class ProducerConstructorInterceptor implements InstanceConstructorInterceptor {
    
        @Override
        public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
            ProducerConfig config = (ProducerConfig) allArguments[0];
            objInst.setSkyWalkingDynamicField(StringUtil.join(';', config.getList("bootstrap.servers")
                                                                         .toArray(new String[0])));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意

    能看到这里使用_$EnhancedClassField_ws字段来保存一些数据方便后续使用,这也是为什么要执行这段逻辑,设置此字段的原因

    if (!typeDescription.isAssignableTo(EnhancedInstance.class)) {
      if (!context.isObjectExtended()) {
          //给要增强的类添加_$EnhancedClassField_ws字段,
          //并实现了EnhancedInstance接口的set/get方法,来获取这个字段
          //新增这个字段的作用是可以放置自己的数据,然后通过这两个set/get方法来存放和拿取
          newClassBuilder = newClassBuilder.defineField(
              CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE)
                                           .implement(EnhancedInstance.class)
                                           .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME));
          context.extendObjectCompleted();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    实例方法增强

    首先看这段逻辑

    ElementMatcher.Junction<MethodDescription> junction = not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher());
    if (instanceMethodsInterceptPoint instanceof DeclaredInstanceMethodsInterceptPoint) {
        //拦截到的方法必须是当前类上的 注解匹配到的方法有可能不是当前类上的
        junction = junction.and(ElementMatchers.<MethodDescription>isDeclaredBy(typeDescription));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 比如说,要对Student.add()方法增强,那么直接指定类名即可,但如果想对所有Controller的SpringMVC控制层的方法进行增强,那么就要使用注解。
    • 但有可能通过注解匹配到的方法不是当前类上的,所以判断如果拦截点为DeclaredInstanceMethodsInterceptPoint会新增匹配条件:获取到的方法必须是当前类上的
      非JDK的类库是被ConstructorInter所增强的

    我们依旧先分析不是JDK类库的类

    不修改原方法的参数
    newClassBuilder = newClassBuilder.method(junction)
                                    .intercept(MethodDelegation.withDefaultConfiguration()
                                    .to(new InstMethodsInter(interceptor, classLoader)));
    
    • 1
    • 2
    • 3

    具体逻辑在InstMethodsInter

    InstMethodsInter

    public class InstMethodsInter {
        private static final ILog LOGGER = LogManager.getLogger(InstMethodsInter.class);
    
        /**
         * An {@link InstanceMethodsAroundInterceptor} This name should only stay in {@link String}, the real {@link Class}
         * type will trigger classloader failure. If you want to know more, please check on books about Classloader or
         * Classloader appointment mechanism.
         */
        private InstanceMethodsAroundInterceptor interceptor;
    
        /**
         * @param instanceMethodsAroundInterceptorClassName class full name.
         */
        public InstMethodsInter(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) {
            try {
                //使用自定义加载器加载拦截器
                interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
            } catch (Throwable t) {
                throw new PluginException("Can't create InstanceMethodsAroundInterceptor.", t);
            }
        }
    
        /**
         * Intercept the target instance method.
         *
         * @param obj          target class instance.
         * @param allArguments all method arguments
         * @param method       method description.
         * @param zuper        the origin call ref.
         * @return the return value of target instance method.
         * @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
         *                   bug, if anything triggers this condition ).
         */
        @RuntimeType
        public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper,
            @Origin Method method) throws Throwable {
            EnhancedInstance targetObject = (EnhancedInstance) obj;
    
            MethodInterceptResult result = new MethodInterceptResult();
            try {
                //前置增强
                interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), result);
            } catch (Throwable t) {
                LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
            }
    
            Object ret = null;
            try {
                if (!result.isContinue()) {
                    ret = result._ret();
                } else {
                    //执行原有方法
                    ret = zuper.call();
                }
            } catch (Throwable t) {
                try {
                    //异常增强
                    interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t);
                } catch (Throwable t2) {
                    LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
                }
                throw t;
            } finally {
                try {
                    //后置增强
                    ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret);
                } catch (Throwable t) {
                    LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
                }
            }
            return ret;
        }
    }
    
    • 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
    修改原方法的参数
    newClassBuilder = newClassBuilder.method(junction)
                      .intercept(MethodDelegation.withDefaultConfiguration()
                                     .withBinders(Morph.Binder.install(OverrideCallable.class))
                                     .to(new InstMethodsInterWithOverrideArgs(interceptor, classLoader)));
    
    • 1
    • 2
    • 3
    • 4

    具体逻辑在InstMethodsInterWithOverrideArgs

    InstMethodsInterWithOverrideArgs

    public class InstMethodsInterWithOverrideArgs {
        private static final ILog LOGGER = LogManager.getLogger(InstMethodsInterWithOverrideArgs.class);
    
        /**
         * An {@link InstanceMethodsAroundInterceptor} This name should only stay in {@link String}, the real {@link Class}
         * type will trigger classloader failure. If you want to know more, please check on books about Classloader or
         * Classloader appointment mechanism.
         */
        private InstanceMethodsAroundInterceptor interceptor;
    
        /**
         * @param instanceMethodsAroundInterceptorClassName class full name.
         */
        public InstMethodsInterWithOverrideArgs(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) {
            try {
                interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
            } catch (Throwable t) {
                throw new PluginException("Can't create InstanceMethodsAroundInterceptor.", t);
            }
        }
    
        /**
         * Intercept the target instance method.
         *
         * @param obj          target class instance.
         * @param allArguments all method arguments
         * @param method       method description.
         * @param zuper        the origin call ref.
         * @return the return value of target instance method.
         * @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
         *                   bug, if anything triggers this condition ).
         */
        @RuntimeType
        public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @Origin Method method,
            @Morph OverrideCallable zuper) throws Throwable {
            EnhancedInstance targetObject = (EnhancedInstance) obj;
    
            MethodInterceptResult result = new MethodInterceptResult();
            try {
                interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), result);
            } catch (Throwable t) {
                LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
            }
    
            Object ret = null;
            try {
                if (!result.isContinue()) {
                    ret = result._ret();
                } else {
                    ret = zuper.call(allArguments);
                }
            } catch (Throwable t) {
                try {
                    interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t);
                } catch (Throwable t2) {
                    LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
                }
                throw t;
            } finally {
                try {
                    ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret);
                } catch (Throwable t) {
                    LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
                }
            }
            return ret;
        }
    }
    
    • 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

    可以看到实例方法的增强逻辑和静态方法的大致相同

    这里面有个问题,为什么用zuper.call()执行原方法的调用,不能替换成method.invoke(clazz.newInstance())吗?

    这里需要借助一个Java实时反编译工具friday,看看项目执行SkyWalking Agent之后反编译的结构

    原始类:

    @RestController
    @RequestMapping("/api/hello")
    public class UserController {
    
        @GetMapping
        public String sayHello() {
            return "hello";
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    增强后:

    @RestController
    @RequestMapping(value={"/test"})
    public class TestController
    implements EnhancedInstance {
        private volatile Object _$EnhancedClassField_ws;
        public static volatile /* synthetic */ InstMethodsInter delegate$mvblfc0;
        public static volatile /* synthetic */ InstMethodsInter delegate$hfbkh30;
        public static volatile /* synthetic */ ConstructorInter delegate$gr07501;
        private static final /* synthetic */ Method cachedValue$kkbY4FHP$ldstch2;
        public static volatile /* synthetic */ InstMethodsInter delegate$lvp69q1;
        public static volatile /* synthetic */ InstMethodsInter delegate$mpv7fs0;
        public static volatile /* synthetic */ ConstructorInter delegate$v0q1e31;
        private static final /* synthetic */ Method cachedValue$Hx3zGNqH$ldstch2;
    
        public TestController() {
            this(null);
            delegate$v0q1e31.intercept((Object)this, new Object[0]);
        }
    
        private /* synthetic */ TestController(auxiliary.YsFzTfDy ysFzTfDy) {
        }
    
        @RequestMapping
        public String test() {
            return (String)delegate$lvp69q1.intercept((Object)this, new Object[0], (Callable)new auxiliary.pEJy33Ip(this), cachedValue$Hx3zGNqH$ldstch2);
        }
    
        private /* synthetic */ String test$original$70VVkKcL() {
            return "sucess";
        }
    
        static {
            ClassLoader.getSystemClassLoader().loadClass("org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.Nexus").getMethod("initialize", Class.class, Integer.TYPE).invoke(null, TestController.class, 544534948);
            cachedValue$Hx3zGNqH$ldstch2 = TestController.class.getMethod("test", new Class[0]);
        }
    
        final /* synthetic */ String test$original$70VVkKcL$accessor$Hx3zGNqH() {
            return this.test$original$70VVkKcL();
        }
    }
    
    • 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

    然后还要再看一下SkyWalkingAgent.premain()

    public static void premain(String agentArgs, Instrumentation instrumentation) throws PluginException {
        final PluginFinder pluginFinder;
        //省略...
                    //指定byteBuddy要拦截的类
        agentBuilder.type(pluginFinder.buildMatch())
                    //指定字节码增强的工具
                    .transform(new Transformer(pluginFinder))
                    //redefine和retransformation的区别在于是否保留修改前的内容
                    .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
                    .with(new RedefinitionListener())
                    .with(new Listener())
                    //将agent安装到instrumentation
                    .installOn(instrumentation);
        //省略...            
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • redefineretransform的区别在于是否保留修改前的内容,从反编译的内容可以看到test()方法的内容已经被修改掉了,原方法被重命名为test o r i g i n a l original original+随机字符串
    • 新的test()方法中调用了InstMethodsInter的intercept()方法,最后传入的intercept()的method参数是被修改后的test()方法,不再指向原生的test()方法,如果在InstMethodsInter使用method.invoke(clazz.newInstance())就相当于自己调自己,就会死递归下去

    总结

    • 构造方法
      • 是JDK类库的类
      • 不是JDK类库的类
        • 在原有的构造方法执行完后,在执行onContruct进行增强
    • 实例方法
      • 和静态方法相同

    以上就是构造方法和实例方法增强逻辑。

    在我们执行增强逻辑前,我们先看下插件拦截类的加载过程

    • 静态方法增强前的加载
    //clazz 要修改的字节码的原生类
    StaticMethodsAroundInterceptor interceptor = InterceptorInstanceLoader.load(staticMethodsAroundInterceptorClassName, clazz
                .getClassLoader());
    
    • 1
    • 2
    • 3
    • 构造/实例方法前的加载
    //当前拦截到的类的类加载器
    interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
    
    • 1
    • 2

    这个加载的方法很重要,它是将插件拦截类和业务执行类的类加载器进行融合的关键,也是skywalking的精髓所在,下篇文章我们来详细的分析下。

  • 相关阅读:
    ubuntu如何开启22端口支持ssh访问
    js input 正则保留2位小数中文拼音输入问题 + 限制输入整数的方案
    分布式锁之Redis实现
    Ubuntu系统硬盘挂载
    java基于Springboot+vue的球鞋销售商城网站 elementui
    电机剧烈振动的原因及解决办法(附电机振动监测方案)
    分布式协调系统ZooKeeper实践与原理剖析
    nginx负载均衡和反向代理配置实例说明(内容来自网上,学习笔记,仅供交流学习使用无商业目的,如有侵权,通知我立马删除)
    Scala 运算符
    maven聚合工程整合springboot+mybatisplus遇到的问题
  • 原文地址:https://blog.csdn.net/guntun8987/article/details/134416664