2929import net .bytebuddy .pool .TypePool ;
3030import net .bytebuddy .utility .JavaModule ;
3131import net .bytebuddy .utility .nullability .MaybeNull ;
32- import org .apache .skywalking .apm .agent .core .plugin .AbstractClassEnhancePluginDefine ;
3332import org .apache .skywalking .apm .agent .core .plugin .interceptor .enhance .EnhancedInstance ;
3433
3534import java .io .Serializable ;
3837import java .util .HashMap ;
3938import java .util .List ;
4039import java .util .Map ;
40+ import java .util .Set ;
41+ import java .util .concurrent .ConcurrentHashMap ;
4142import java .util .stream .Collectors ;
4243
4344/**
@@ -109,7 +110,7 @@ public TypeDescription apply(String name,
109110 }
110111 }
111112 // wrap result
112- return new SWTypeDescriptionWrapper (delegate .apply (name , type , typePool , circularityLock , classLoader , module ), nameTrait );
113+ return new SWTypeDescriptionWrapper (delegate .apply (name , type , typePool , circularityLock , classLoader , module ), nameTrait , classLoader , name );
113114 }
114115
115116 /**
@@ -122,25 +123,40 @@ static class SWTypeDescriptionWrapper extends TypeDescription.AbstractBase imple
122123 */
123124 private static final long serialVersionUID = 1L ;
124125
125- private static final List <String > IGNORED_INTERFACES = Arrays .asList (EnhancedInstance .class .getName ());
126-
127- private static final List <String > IGNORED_FIELDS = Arrays .asList (AbstractClassEnhancePluginDefine .CONTEXT_ATTR_NAME );
126+ /**
127+ * Original type cache.
128+ * classloader hashcode -> ( typeName -> type cache )
129+ */
130+ private static final Map <Integer , Map <String , TypeCache >> CLASS_LOADER_TYPE_CACHE = new ConcurrentHashMap <>();
128131
129- private static final List <String > IGNORED_METHODS = Arrays .asList ("getSkyWalkingDynamicField" , "setSkyWalkingDynamicField" );
132+ private static final List <String > IGNORED_INTERFACES = Arrays .asList (EnhancedInstance . class . getName () );
130133
131134 private MethodList <MethodDescription .InDefinedShape > methods ;
132135
133136 private FieldList <FieldDescription .InDefinedShape > fields ;
134137
135138 private final String nameTrait ;
136139
140+ private ClassLoader classLoader ;
141+
142+ private String typeName ;
143+
137144 private TypeList .Generic interfaces ;
138145
139146 private TypeDescription delegate ;
140147
141- public SWTypeDescriptionWrapper (TypeDescription delegate , String nameTrait ) {
148+ public SWTypeDescriptionWrapper (TypeDescription delegate , String nameTrait , ClassLoader classLoader , String typeName ) {
142149 this .delegate = delegate ;
143150 this .nameTrait = nameTrait ;
151+ this .classLoader = classLoader ;
152+ this .typeName = typeName ;
153+ }
154+
155+ private TypeCache getTypeCache () {
156+ int classLoaderHashCode = classLoader != null ? classLoader .hashCode () : 0 ;
157+ Map <String , TypeCache > typeCacheMap = CLASS_LOADER_TYPE_CACHE .computeIfAbsent (classLoaderHashCode , k -> new ConcurrentHashMap <>());
158+ TypeCache typeCache = typeCacheMap .computeIfAbsent (typeName , k -> new TypeCache (typeName ));
159+ return typeCache ;
144160 }
145161
146162 @ Override
@@ -164,14 +180,16 @@ public TypeList.Generic getInterfaces() {
164180 public FieldList <FieldDescription .InDefinedShape > getDeclaredFields () {
165181 if (this .fields == null ) {
166182 FieldList <FieldDescription .InDefinedShape > declaredFields = delegate .getDeclaredFields ();
167- if (declaredFields .stream ()
168- .anyMatch (f -> f .getName ().contains (nameTrait ) || IGNORED_FIELDS .contains (f .getName ()))) {
169- // Remove dynamic field tokens generated by SkyWalking
183+ TypeCache typeCache = getTypeCache ();
184+ if (typeCache .fieldNames == null ) {
185+ // save origin fields
186+ typeCache .fieldNames = declaredFields .stream ().map (WithRuntimeName ::getName ).collect (Collectors .toSet ());
187+ fields = declaredFields ;
188+ } else {
189+ // return origin fields
170190 fields = new FieldList .Explicit <>(declaredFields .stream ()
171- .filter (f -> ! f . getName (). contains ( nameTrait ) && ! IGNORED_FIELDS .contains (f .getName ()))
191+ .filter (f -> typeCache . fieldNames .contains (f .getName ()))
172192 .collect (Collectors .toList ()));
173- } else {
174- fields = declaredFields ;
175193 }
176194 }
177195 return fields ;
@@ -181,14 +199,17 @@ public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
181199 public MethodList <MethodDescription .InDefinedShape > getDeclaredMethods () {
182200 if (this .methods == null ) {
183201 MethodList <MethodDescription .InDefinedShape > declaredMethods = delegate .getDeclaredMethods ();
184- if (declaredMethods .stream ()
185- .anyMatch (m -> m .getName ().contains (nameTrait ) || IGNORED_METHODS .contains (m .getName ()))) {
186- // Remove dynamic method tokens generated by SkyWalking
202+ TypeCache typeCache = getTypeCache ();
203+ if (typeCache .methodCodes == null ) {
204+ // save original methods
205+ typeCache .methodCodes = declaredMethods .stream ().map (m -> m .toString ().hashCode ()).collect (Collectors .toSet ());
206+ methods = declaredMethods ;
207+ } else {
208+ // return original methods in the same order, remove dynamic method tokens generated by SkyWalking and ByteBuddy
209+ // remove generated methods for delegating superclass methods, such as Jedis.
187210 methods = new MethodList .Explicit <>(declaredMethods .stream ()
188- .filter (m -> ! m . getName () .contains (nameTrait ) && ! IGNORED_METHODS . contains ( m . getName ()))
211+ .filter (m -> typeCache . methodCodes .contains (m . toString (). hashCode ()))
189212 .collect (Collectors .toList ()));
190- } else {
191- methods = declaredMethods ;
192213 }
193214 }
194215 return methods ;
@@ -332,4 +353,14 @@ public int getModifiers() {
332353 return delegate .getModifiers ();
333354 }
334355 }
356+
357+ static class TypeCache {
358+ private String typeName ;
359+ private Set <Integer > methodCodes ;
360+ private Set <String > fieldNames ;
361+
362+ public TypeCache (String typeName ) {
363+ this .typeName = typeName ;
364+ }
365+ }
335366}
0 commit comments