From 138262f95a7d745097840440ed608af415827dbc Mon Sep 17 00:00:00 2001 From: "li.can" Date: Fri, 16 Nov 2018 23:00:50 +0800 Subject: [PATCH] spring inherit issue (#1914) --- .../AbstractClassEnhancePluginDefine.java | 17 +++---- ...DeclaredInstanceMethodsInterceptPoint.java | 28 +++++++++++ .../enhance/ClassEnhancePluginDefine.java | 48 ++++++++++--------- .../skywalking/apm/agent/SkyWalkingAgent.java | 17 +++---- .../v3/define/ControllerInstrumentation.java | 7 ++- .../AbstractControllerInstrumentation.java | 9 ++-- 6 files changed, 76 insertions(+), 50 deletions(-) create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/DeclaredInstanceMethodsInterceptPoint.java diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java index ed975e500..2d838465d 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java @@ -19,11 +19,12 @@ package org.apache.skywalking.apm.agent.core.plugin; +import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine; -import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import org.apache.skywalking.apm.agent.core.logging.api.ILog; import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import org.apache.skywalking.apm.util.StringUtil; /** @@ -38,16 +39,16 @@ public abstract class AbstractClassEnhancePluginDefine { /** * Main entrance of enhancing the class. * - * @param transformClassName target class. + * @param typeDescription target class description. * @param builder byte-buddy's builder to manipulate target class's bytecode. * @param classLoader load the given transformClass * @return the new builder, or null if not be enhanced. * @throws PluginException when set builder failure. */ - public DynamicType.Builder define(String transformClassName, - DynamicType.Builder builder, ClassLoader classLoader, EnhanceContext context) throws PluginException { + public DynamicType.Builder define(TypeDescription typeDescription, + DynamicType.Builder builder, ClassLoader classLoader, EnhanceContext context) throws PluginException { String interceptorDefineClassName = this.getClass().getName(); - + String transformClassName = typeDescription.getTypeName(); if (StringUtil.isEmpty(transformClassName)) { logger.warn("classname of being intercepted is not defined by {}.", interceptorDefineClassName); return null; @@ -72,7 +73,7 @@ public abstract class AbstractClassEnhancePluginDefine { /** * find origin class source code for interceptor */ - DynamicType.Builder newClassBuilder = this.enhance(transformClassName, builder, classLoader, context); + DynamicType.Builder newClassBuilder = this.enhance(typeDescription, builder, classLoader, context); context.initializationStageCompleted(); logger.debug("enhance class {} by {} completely.", transformClassName, interceptorDefineClassName); @@ -80,7 +81,7 @@ public abstract class AbstractClassEnhancePluginDefine { return newClassBuilder; } - protected abstract DynamicType.Builder enhance(String enhanceOriginClassName, + protected abstract DynamicType.Builder enhance(TypeDescription typeDescription, DynamicType.Builder newClassBuilder, ClassLoader classLoader, EnhanceContext context) throws PluginException; /** diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/DeclaredInstanceMethodsInterceptPoint.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/DeclaredInstanceMethodsInterceptPoint.java new file mode 100644 index 000000000..909392fe8 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/DeclaredInstanceMethodsInterceptPoint.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.agent.core.plugin.interceptor; + +/** + * this interface for those who only want to enhance declared method in case of some unexpected issue, + * such as spring controller + * + * @author lican + */ +public interface DeclaredInstanceMethodsInterceptPoint extends InstanceMethodsInterceptPoint { +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java index 654461f58..d019097e3 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java @@ -19,20 +19,21 @@ package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.FieldAccessor; import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.implementation.SuperMethodCall; import net.bytebuddy.implementation.bind.annotation.Morph; -import org.apache.skywalking.apm.agent.core.plugin.AbstractClassEnhancePluginDefine; -import org.apache.skywalking.apm.agent.core.plugin.EnhanceContext; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.EnhanceException; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; -import org.apache.skywalking.apm.agent.core.plugin.PluginException; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; import org.apache.skywalking.apm.agent.core.logging.api.ILog; import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.agent.core.plugin.AbstractClassEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.EnhanceContext; +import org.apache.skywalking.apm.agent.core.plugin.PluginException; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.*; import org.apache.skywalking.apm.util.StringUtil; import static net.bytebuddy.jar.asm.Opcodes.ACC_PRIVATE; @@ -61,17 +62,17 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi * Begin to define how to enhance class. * After invoke this method, only means definition is finished. * - * @param enhanceOriginClassName target class name + * @param typeDescription target class description * @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @return new byte-buddy's builder for further manipulation. */ @Override - protected DynamicType.Builder enhance(String enhanceOriginClassName, - DynamicType.Builder newClassBuilder, ClassLoader classLoader, - EnhanceContext context) throws PluginException { - newClassBuilder = this.enhanceClass(enhanceOriginClassName, newClassBuilder, classLoader); + protected DynamicType.Builder enhance(TypeDescription typeDescription, + DynamicType.Builder newClassBuilder, ClassLoader classLoader, + EnhanceContext context) throws PluginException { + newClassBuilder = this.enhanceClass(typeDescription, newClassBuilder, classLoader); - newClassBuilder = this.enhanceInstance(enhanceOriginClassName, newClassBuilder, classLoader, context); + newClassBuilder = this.enhanceInstance(typeDescription, newClassBuilder, classLoader, context); return newClassBuilder; } @@ -79,16 +80,16 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi /** * Enhance a class to intercept constructors and class instance methods. * - * @param enhanceOriginClassName target class name + * @param typeDescription target class description * @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @return new byte-buddy's builder for further manipulation. */ - private DynamicType.Builder enhanceInstance(String enhanceOriginClassName, + private 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; @@ -144,10 +145,13 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi if (StringUtil.isEmpty(interceptor)) { throw new EnhanceException("no InstanceMethodsAroundInterceptor define to enhance class " + enhanceOriginClassName); } - + ElementMatcher.Junction junction = not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher()); + if (instanceMethodsInterceptPoint instanceof DeclaredInstanceMethodsInterceptPoint) { + junction = junction.and(ElementMatchers.isDeclaredBy(typeDescription)); + } if (instanceMethodsInterceptPoint.isOverrideArgs()) { newClassBuilder = - newClassBuilder.method(not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher())) + newClassBuilder.method(junction) .intercept( MethodDelegation.withDefaultConfiguration() .withBinders( @@ -157,7 +161,7 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi ); } else { newClassBuilder = - newClassBuilder.method(not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher())) + newClassBuilder.method(junction) .intercept( MethodDelegation.withDefaultConfiguration() .to(new InstMethodsInter(interceptor, classLoader)) @@ -186,14 +190,14 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi /** * Enhance a class to intercept class static methods. * - * @param enhanceOriginClassName target class name + * @param typeDescription target class description * @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @return new byte-buddy's builder for further manipulation. */ - private DynamicType.Builder enhanceClass(String enhanceOriginClassName, + private DynamicType.Builder enhanceClass(TypeDescription typeDescription, DynamicType.Builder newClassBuilder, ClassLoader classLoader) throws PluginException { StaticMethodsInterceptPoint[] staticMethodsInterceptPoints = getStaticMethodsInterceptPoints(); - + String enhanceOriginClassName = typeDescription.getTypeName(); if (staticMethodsInterceptPoints == null || staticMethodsInterceptPoints.length == 0) { return newClassBuilder; } diff --git a/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java b/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java index fd3b4a0c4..6dbc30736 100644 --- a/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java +++ b/apm-sniffer/apm-agent/src/main/java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java @@ -18,8 +18,6 @@ package org.apache.skywalking.apm.agent; -import java.lang.instrument.Instrumentation; -import java.util.List; import net.bytebuddy.ByteBuddy; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.NamedElement; @@ -33,15 +31,12 @@ import org.apache.skywalking.apm.agent.core.conf.Config; import org.apache.skywalking.apm.agent.core.conf.SnifferConfigInitializer; import org.apache.skywalking.apm.agent.core.logging.api.ILog; import org.apache.skywalking.apm.agent.core.logging.api.LogManager; -import org.apache.skywalking.apm.agent.core.plugin.AbstractClassEnhancePluginDefine; -import org.apache.skywalking.apm.agent.core.plugin.EnhanceContext; -import org.apache.skywalking.apm.agent.core.plugin.PluginBootstrap; -import org.apache.skywalking.apm.agent.core.plugin.PluginException; -import org.apache.skywalking.apm.agent.core.plugin.PluginFinder; +import org.apache.skywalking.apm.agent.core.plugin.*; -import static net.bytebuddy.matcher.ElementMatchers.nameContains; -import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; -import static net.bytebuddy.matcher.ElementMatchers.not; +import java.lang.instrument.Instrumentation; +import java.util.List; + +import static net.bytebuddy.matcher.ElementMatchers.*; /** * The main entrance of sky-waking agent, based on javaagent mechanism. @@ -114,7 +109,7 @@ public class SkyWalkingAgent { DynamicType.Builder newBuilder = builder; EnhanceContext context = new EnhanceContext(); for (AbstractClassEnhancePluginDefine define : pluginDefines) { - DynamicType.Builder possibleNewBuilder = define.define(typeDescription.getTypeName(), newBuilder, classLoader, context); + DynamicType.Builder possibleNewBuilder = define.define(typeDescription, newBuilder, classLoader, context); if (possibleNewBuilder != null) { newBuilder = possibleNewBuilder; } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v3/define/ControllerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v3/define/ControllerInstrumentation.java index dd24d03e6..9f2fcaffe 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v3/define/ControllerInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v3/define/ControllerInstrumentation.java @@ -22,13 +22,12 @@ package org.apache.skywalking.apm.plugin.spring.mvc.v3.define; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.DeclaredInstanceMethodsInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch; import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; -import static net.bytebuddy.matcher.ElementMatchers.any; -import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; -import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.*; import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.REQUEST_MAPPING_METHOD_INTERCEPTOR; /** @@ -63,7 +62,7 @@ public class ControllerInstrumentation extends AbstractSpring3Instrumentation { @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { return new InstanceMethodsInterceptPoint[] { - new InstanceMethodsInterceptPoint() { + new DeclaredInstanceMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { return isAnnotatedWith(named(REQUEST_MAPPING_ENHANCE_ANNOTATION)); diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/AbstractControllerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/AbstractControllerInstrumentation.java index 225b657bb..a8909c1ed 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/AbstractControllerInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/define/AbstractControllerInstrumentation.java @@ -21,14 +21,13 @@ package org.apache.skywalking.apm.plugin.spring.mvc.v4.define; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.DeclaredInstanceMethodsInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch; import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants; -import static net.bytebuddy.matcher.ElementMatchers.any; -import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; -import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.*; /** * {@link ControllerInstrumentation} enhance all constructor and method annotated with @@ -66,7 +65,7 @@ public abstract class AbstractControllerInstrumentation extends AbstractSpring4I @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { return new InstanceMethodsInterceptPoint[] { - new InstanceMethodsInterceptPoint() { + new DeclaredInstanceMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { return isAnnotatedWith(named("org.springframework.web.bind.annotation.RequestMapping")); @@ -82,7 +81,7 @@ public abstract class AbstractControllerInstrumentation extends AbstractSpring4I return false; } }, - new InstanceMethodsInterceptPoint() { + new DeclaredInstanceMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { return isAnnotatedWith(named("org.springframework.web.bind.annotation.GetMapping"))