raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.16k stars 790 forks source link

Publish blocking #1662

Open SongTing0711 opened 1 month ago

SongTing0711 commented 1 month ago
1.14.9 When I enhance all classes under a package, every time I reach a subclass enhanced by cglib, no more logs are generated, and system publishing does not continue This is one of the code segments public class StaticApplicationContext$$EnhancerBySpringCGLIB$$2d3e27aa extends StaticApplicationContext implements EnhancedConfiguration { private boolean CGLIB$BOUND; public static Object CGLIB$FACTORY_DATA; private static final ThreadLocal CGLIB$THREAD_CALLBACKS; private static final Callback[] CGLIB$STATIC_CALLBACKS; private MethodInterceptor CGLIB$CALLBACK_0; private MethodInterceptor CGLIB$CALLBACK_1; private NoOp CGLIB$CALLBACK_2; private static Object CGLIB$CALLBACK_FILTER; private static final Method CGLIB$setBeanFactory$5$Method; private static final MethodProxy CGLIB$setBeanFactory$5$Proxy; private static final Object[] CGLIB$emptyArgs; public BeanFactory $$beanFactory; static void CGLIB$STATICHOOK1() { MethodArg var10000; label43: { try { ProfilerAction var0 = LogActionHolder.getLogAction("profiler.agent.instrumentation.action.MethodProfilerActionImpl"); if (Objects.nonNull(var0)) { var10000 = var0.onMethodEnter(new Object[0], Class.forName("com.ctrip.corp.intlflight.search.config.StaticApplicationContext$$EnhancerBySpringCGLIB$$2d3e27aa").getDeclaredMethod("CGLIB$STATICHOOK1"), false); break label43; } } catch (Throwable var7) { System.out.println("MethodServiceAdvice error" + var7); } var10000 = null; }
raphw commented 1 month ago

Did you take a thread dump? Maybe you intercept a method and invoke the proxy again? Or you lock the same object from different threads.

SongTing0711 commented 1 month ago

Did you take a thread dump? Maybe you intercept a method and invoke the proxy again? Or you lock the same object from different threads.

Perhaps so, I tried to configure the class that was not enhanced, and the result was successful. However, this is not safe. I tried the following code again, hoping to block the classes that have already been enhanced by cglib, but it still hasn't been blocked why? private static class InnerTransformer implements AgentBuilder.Transformer { @Override public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) { return builder.visit(Advice.to(MethodServiceAdvice.class) .on(ElementMatchers.not(ElementMatchers.isConstructor()) .and(ElementMatchers .noneOf(ElementMatchers.hasSuperType(ElementMatchers.named("StaticApplicationContext")))) .and(ElementMatchers.not(ElementMatchers.isTypeInitializer())) .and(ElementMatchers.not(ElementMatchers.isSetter())) .and(ElementMatchers.not(ElementMatchers.isGetter())) .and(ElementMatchers.not(ElementMatchers.nameStartsWith("net.bytebuddy.generated"))) .and(ElementMatchers.not(ElementMatchers.nameContains("EnhancerBySpringCGLIB"))) .and(ElementMatchers.not(ElementMatchers.nameContains("$$"))) .and(ElementMatchers.not(ElementMatchers.nameContains("FastClassByCGLIB"))) .and(ElementMatchers.not(ElementMatchers.nameContains("MethodInterceptor"))))); } }

SongTing0711 commented 1 month ago

take a thread dump

I tried to take a thread dump, but the PID of tomcat kept changing, so I couldn't get it

raphw commented 1 month ago

You can use jps to find it.

SongTing0711 commented 1 month ago

You can use jps to find it. I used JPS, but you can see that the displayed PID keeps changing

image
SongTing0711 commented 1 month ago

You can use jps to find it. I used JPS, but you can see that the displayed PID keeps changing

image

Can you take a look at why the filtering above doesn't work

private static class InnerTransformer implements AgentBuilder.Transformer { @OverRide public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) { return builder.visit(Advice.to(MethodServiceAdvice.class) .on(ElementMatchers.not(ElementMatchers.isConstructor()) .and(ElementMatchers .noneOf(ElementMatchers.hasSuperType(ElementMatchers.named("StaticApplicationContext")))) .and(ElementMatchers.not(ElementMatchers.isTypeInitializer())) .and(ElementMatchers.not(ElementMatchers.isSetter())) .and(ElementMatchers.not(ElementMatchers.isGetter())) .and(ElementMatchers.not(ElementMatchers.nameStartsWith("net.bytebuddy.generated"))) .and(ElementMatchers.not(ElementMatchers.nameContains("EnhancerBySpringCGLIB"))) .and(ElementMatchers.not(ElementMatchers.nameContains("$$"))) .and(ElementMatchers.not(ElementMatchers.nameContains("FastClassByCGLIB"))) .and(ElementMatchers.not(ElementMatchers.nameContains("MethodInterceptor"))))); } }

SongTing0711 commented 1 month ago

I used JPS, but you can see that the displayed PID keeps changing image

raphw commented 1 month ago

Are those processes short lived? If so, it's hard to hit a target. Maybe you should change JAVA_TOOL_OPTIONS to add your agent when any Java process is starting up?

SongTing0711 commented 1 month ago

Can you take a look at why the filtering above doesn't work

private static class InnerTransformer implements AgentBuilder.Transformer {
@OverRide
public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) {
return builder.visit(Advice.to(MethodServiceAdvice.class)
.on(ElementMatchers.not(ElementMatchers.isConstructor())
.and(ElementMatchers
.noneOf(ElementMatchers.hasSuperType(ElementMatchers.named("StaticApplicationContext"))))
.and(ElementMatchers.not(ElementMatchers.isTypeInitializer()))
.and(ElementMatchers.not(ElementMatchers.isSetter()))
.and(ElementMatchers.not(ElementMatchers.isGetter()))
.and(ElementMatchers.not(ElementMatchers.nameStartsWith("net.bytebuddy.generated")))
.and(ElementMatchers.not(ElementMatchers.nameContains("EnhancerBySpringCGLIB")))
.and(ElementMatchers.not(ElementMatchers.nameContains("$$")))
.and(ElementMatchers.not(ElementMatchers.nameContains("FastClassByCGLIB")))
.and(ElementMatchers.not(ElementMatchers.nameContains("MethodInterceptor")))));
}
}
raphw commented 1 month ago

What filtering do you mean?

SongTing0711 commented 1 month ago

What I mean is that based on the previous investigation, it seems that the classes enhanced by cglib have been enhanced again by bytebuddy. Therefore, I want to use the ElementMatchers provided by bytebuddy to filter all the classes enhanced by cglib, which is this code, but it still cannot be successfully filtered private static class InnerTransformer implements AgentBuilder.Transformer { @OverRide public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) { return builder.visit(Advice.to(MethodServiceAdvice.class) .on(ElementMatchers.not(ElementMatchers.isConstructor()) .and(ElementMatchers .noneOf(ElementMatchers.hasSuperType(ElementMatchers.named("StaticApplicationContext")))) .and(ElementMatchers.not(ElementMatchers.isTypeInitializer())) .and(ElementMatchers.not(ElementMatchers.isSetter())) .and(ElementMatchers.not(ElementMatchers.isGetter())) .and(ElementMatchers.not(ElementMatchers.nameStartsWith("net.bytebuddy.generated"))) .and(ElementMatchers.not(ElementMatchers.nameContains("EnhancerBySpringCGLIB"))) .and(ElementMatchers.not(ElementMatchers.nameContains("$$"))) .and(ElementMatchers.not(ElementMatchers.nameContains("FastClassByCGLIB"))) .and(ElementMatchers.not(ElementMatchers.nameContains("MethodInterceptor"))))); } }

raphw commented 1 month ago

You combine all these matchers. You likely want to use .or which implies that any condition holds.