redefine for java.time.Clock#instant not work with jdk 17 runtime
jvm runtime: openjdk17 bytebudy version: 1.14.3
i tried to interrupt " java.time.Clock#instant" method with below code, but it did not work?
new AgentBuilder.Default()
.disableClassFormatChanges()
.ignore(nameStartsWith("net.bytebuddy."))
.with(new TransformListener())
.with(new ByteBuddy().with(Implementation.Context.Disabled.Factory.INSTANCE))
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
.with(AgentBuilder.TypeStrategy.Default.REDEFINE)
.type(hasSuperClass(ElementMatchers.named("java.time.Clock")))
.transform((builder, typeDescription, classLoader, module, protectionDomain) -> builder
.method(ElementMatchers.named("instant"))
.intercept(Advice.to(ClockInterceptor.class).wrap(StubMethod.INSTANCE)))
.installOn(inst);
ClockInterceptor code is:
@Slf4j
public class ClockInterceptor {
@Advice.OnMethodExit(suppress = Throwable.class)
public static void onExit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Instant result) {
if (ClockMockDispatcher.dispatcher != null) {
long mockMillis = ClockMockDispatcher.dispatcher.mockMillis();
if (mockMillis > 0) {
result = Instant.ofEpochMilli(mockMillis);
}
}
}
}
Apply Advice as a visitor:
builder.visit(Advice.to(ClockInterceptor.class).on(ElementMatchers.named("instant"))
Apply
Adviceas a visitor:builder.visit(Advice.to(ClockInterceptor.class).on(ElementMatchers.named("instant"))
it works, but why? i'm new to bytebuddy
If you apply advice as a visitor, it simply decorates existing methods. The class file as such remains intact, however.
If you apply it as an interceptor, it replaces the current method with a new implementation. This is a more powerful concept, and allows more adjustments, but is also requiring some changes to the class file. This is not allowed (by the JVM) for retransformations.
If you apply advice as a visitor, it simply decorates existing methods. The class file as such remains intact, however.
If you apply it as an interceptor, it replaces the current method with a new implementation. This is a more powerful concept, and allows more adjustments, but is also requiring some changes to the class file. This is not allowed (by the JVM) for retransformations.
- but the old code did work in jdk 8?
- when i rewrite with AgentBuilder.TypeStrategy.Default.REBASE, it does not work too
new AgentBuilder.Default()
.disableClassFormatChanges()
.ignore(nameStartsWith("net.bytebuddy."))
.with(new TransformListener())
.with(new ByteBuddy().with(Implementation.Context.Disabled.Factory.INSTANCE))
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
.with(AgentBuilder.TypeStrategy.Default.REBASE)
.type(hasSuperClass(ElementMatchers.named("java.time.Clock")))
.transform((builder, typeDescription, classLoader, module, protectionDomain) -> builder
.method(ElementMatchers.named("instant"))
.intercept(Advice.to(ClockInterceptor.class)))
.installOn(inst);
Yes, you override settings from disableClassFormatChanges() doing so.
If the class is not loaded in JDK 8 before your agent gets active, it will work, but this you cannot rely on.
I assume that the JDK did not load the Java class implicitly prior to the agent booting.