raphw/byte-buddy

Publish blocking

Closed this issue · 12 comments

<byte-buddy.version>1.14.9</byte-buddy.version>

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;
    }

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.

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")))));
}
}

take a thread dump

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

You can use jps to find it.

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

image

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")))));
}
}

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

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?

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")))));
}
}

What filtering do you mean?

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")))));
}
}

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