raphw / byte-buddy

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

I want to use bytebuddy to advice java.time.LocalDateTime #1585

Closed LiuxuyangK closed 6 days ago

LiuxuyangK commented 8 months ago

help! Looking forward to your reply! i want to advice java.time.LocalDateTime,and i use this code:

 new AgentBuilder.Default()
                .enableNativeMethodPrefix("wmsnative")
                .with(byteBuddy.with(Implementation.Context.Disabled.Factory.INSTANCE))
                .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
                .with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
                .with(AgentBuilder.TypeStrategy.Default.REDEFINE)
                .ignore(none())
                .type(ElementMatchers.named("java.time.LocalDateTime"))
                .transform(new AgentBuilder.Transformer() {
                    @Override
                    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) {
                        return builder.method(ElementMatchers.named("now").and(ElementMatchers.takesNoArguments()))
                                .intercept(Advice.to(LocalDateTimeInterceptor.class).wrap(StubMethod.INSTANCE));
                    }
                }).installOn(install);

in the LocalDateTimeInterceptor ,the code is:

  @Advice.OnMethodExit
    public static void now(@Advice.Return(readOnly = false) LocalDateTime x) {
        Long nowSeconds = ContextThreadLocalUtil.get().getNowSeconds();
        x = TimeUtil.longSecTOLocalDateTime(nowSeconds);
    }

ContextThreadLocalUtil is a class that i write

and when i invoke LocalDateTime.now(), exception occurs:

java.lang.NoClassDefFoundError: cn/xxx/util/ContextThreadLocalUtil
        at java.time.LocalDateTime.now(LocalDateTime.java)
raphw commented 8 months ago

LocalDateTime is on the boot loader, the class loader that is the parent of all class loaders. Your agent is however loaded on the system loader. As a result, ContextThreadLocalUtil is not visible to LocalDateTime, yielding the error you see.

Either, you need to inject the util class(es) into the boot loader (Instrumentation allows you to append to that loader) and then you need to change the module import (also via Instrumentation), or, easier, you include all your code in the advice class. The code in the advice is copied into the target method such that no visibility restrictions apply.

LiuxuyangK commented 8 months ago

Thank you very much for your reply. The current solution is to enhance all calls to LocalDateTime. now() in the project, which is a rather clumsy approach. However, we would like to explore the two methods you introduced in the future.

Thank you again! We are about to celebrate the Chinese New Year, which is a joyful holiday. Wishing you a happy Spring Festival!

raphw commented 8 months ago

Glad I could help!

LiuxuyangK commented 6 days ago

您好,我是旭阳。我已经收到了您的邮件。祝您身体健康,万事如意。