使用byte-buddy-agent修改java.util类 [英] Modify java.util class using byte-buddy-agent

查看:111
本文介绍了使用byte-buddy-agent修改java.util类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以使用字节伙伴在java.util类中添加字段?

Is it possible to add a field in java.util class using byte-buddy?

我试图在java.util.concurrent.FutureTask中添加一个字段,并拦截构造函数和一个任意方法来设置和获取字段值.简而言之,我正在尝试向FutureTask添加一个字段,以便即使它们在线程池中运行,也可以将某些值从父级传递给子线程.无法在FutureTask中添加字段?

I am trying to add a field in java.util.concurrent.FutureTask and intercept constructor and an arbitrary method to set and get the field value. In short, I am trying to add a field to FutureTask so that I can pass some value to child thread from parent even if they are running in a thread pool. isn't it possible to add a field in FutureTask?

FutureTaskTransofrmer

FutureTaskTransofrmer

@Override
    protected ElementMatcher.Junction<TypeDescription> getNarrowTypesMatcher() {
        return named("java.util.concurrent.FutureTask");
    }

    @Override
    public AgentBuilder.Transformer getTransformer() {

        return (builder, typeDescription, classLoader, module) -> {
            beforeTransformation(typeDescription, classLoader);

            return builder
                    .defineField("pit", String.class)
                    .constructor(ElementMatchers.any())
                    .intercept(Advice.to(SetPitAdvice.class))
                    .method(named("run"))
                    .intercept(Advice.to(GetPitAdvice.class))
                    ;
        };

    }

GetPitAdvice

GetPitAdvice

    @Advice.OnMethodEnter
    public static void getValues(@Advice.FieldValue(value = "pit") String pit)
            throws Exception {

        logger.info("pit in future Task {}", pit);
    }

SetPitAdvice

SetPitAdvice

@Advice.OnMethodExit
    public static void setValues(
            @Advice.FieldValue(value = "pit", readOnly = false) String pit
    )
            throws Exception {

        logger.debug("Setting pit field in FutureTask");

        pit = SimulationRequestContextHolder.get("pit");

    }

AgentBuilder

AgentBuilder

    private static AgentBuilder createAgentBuilder(AutoEvictingCachingBinaryLocator binaryLocator) {
        final ByteBuddy byteBuddy = new ByteBuddy()
                .with(TypeValidation.of(AgentProperties.PROPERTIES.isDebugInstrumentation()))
                .with(MethodGraph.Compiler.ForDeclaredMethods.INSTANCE);

        return new AgentBuilder.Default(byteBuddy)
                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
                .with(getListener())
                .with(binaryLocator)
                .ignore(any(), ClassLoaderNameMatcher.isReflectionClassLoader())
                .or(any(), ClassLoaderNameMatcher.classLoaderWithName("org.codehaus.groovy.runtime.callsite.CallSiteClassLoader"))
                .or(any(), new IsIgnoredClassLoaderElementMatcher())
                .or(nameStartsWith("org.aspectj.")
                        .or(nameStartsWith("org.groovy."))
                        .or(nameStartsWith("com.sun."))
                        .or(nameStartsWith("com.p6spy."))
                        .or(nameStartsWith("net.bytebuddy."))
                        .or(nameStartsWith("org.slf4j.").and(not(nameStartsWith("org.slf4j.impl."))))
                        .or(nameContains("javassist"))
                        .or(nameContains(".asm."))
                        .or(nameStartsWith("com.java.agent.sims")
                        ))
//                .disableClassFormatChanges()
                .enableUnsafeBootstrapInjection()
                ;
    }

onTransformListener显示类已转换

onTransformListener shows the class is transformed

11:27:24.141 [main] INFO com.java.agent.sims.ApplicationClassLoaderMatcher - Instrumenting ClassLoader null: true
11:27:24.186 [main] DEBUG com.java.agent.sims.transformers.ByteBuddyTransformer - TRANSFORM java.util.concurrent.FutureTask (FutureTaskTransformer)
11:27:24.466 [main] INFO com.java.agent.sims.instrument.TransformListener - Class modified by Byte Buddy: java.util.concurrent.FutureTask

但是我的建议拦截都没有被调用.

but none of my advice intercepts are getting called.

推荐答案

如果该类已经加载,则不可能.相反,您可以使用 Instrumentation API将类注入到引导类加载器中,并在此类中存储一个带有弱键的静态映射,您可以在其中放置每个实例的字段值.

If the class is already loaded, this is not possible. Instead, you can inject a class into the bootstrap class loader using the Instrumentation API and have a static map with weak keys stored in this class where you place the field value of each instance.

另外,请注意, until 类是由引导类加载器加载的,而引导类加载器看不到代理所包含的由系统类加载器加载的任何类.因此,建议使用的所有API都必须注入到引导加载程序中.

Also, note that the until classes are loaded by the bootstrap class loader that cannot see any classes contained by your agent which is loaded by the system class loader. Any API used by advice must be injected into the bootstrap loader for this reason.

这篇关于使用byte-buddy-agent修改java.util类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆