gpt4 book ai didi

java - 使用 byte-buddy (System.nanoTime()) 拦截和更改静态本地方法的返回值

转载 作者:行者123 更新时间:2023-12-04 17:30:37 25 4
gpt4 key购买 nike

我想改变 System.nanoTime() 时发生的事情为任意 Java 程序调用(我想倒退时间以帮助容器检查点/恢复用例)。每当System.nanoTime()被调用,我想运行原来的System.nanoTime()然后可能返回不同的值。我正在尝试使用 byte-buddy 和 JVM 检测代理来执行此操作(根据 herehere )。

这是我的尝试:

public final class TimeShifter {
private TimeShifter() {}

private static final Class<?> INTERCEPTOR_CLASS = TimeShiftedSystem.class;

public static void premain(String _arg, Instrumentation instrumentation) throws Exception {
injectBootstrapClasses(instrumentation);
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)
.with(AgentBuilder.TypeStrategy.Default.REDEFINE)
.ignore(
new AgentBuilder.RawMatcher.ForElementMatchers(
ElementMatchers.nameStartsWith("net.bytebuddy.")
.or(ElementMatchers.isSynthetic())
.or(ElementMatchers.nameStartsWith("my.package.name.")),
ElementMatchers.any(),
ElementMatchers.any()))
.with(
new AgentBuilder.Listener.Filtering(
new StringMatcher("java.lang.System", StringMatcher.Mode.EQUALS_FULLY),
AgentBuilder.Listener.StreamWriting.toSystemOut()))
.type(ElementMatchers.named("java.lang.System"))
.transform((builder, type, classLoader, module) ->
// https://stackoverflow.com/questions/49487148/redefine-rebase-native-method
builder.method(ElementMatchers.named("nanoTime"))
.intercept(Advice.to(TimeShiftedSystem.class)))
.installOn(instrumentation);
}

private static void injectBootstrapClasses(Instrumentation instrumentation) throws IOException {
File temp = Files.createTempDirectory("tmp").toFile();
temp.deleteOnExit();

ClassInjector.UsingInstrumentation.of(
temp, ClassInjector.UsingInstrumentation.Target.BOOTSTRAP, instrumentation)
.inject(Collections.singletonMap(
new TypeDescription.ForLoadedType(INTERCEPTOR_CLASS),
ClassFileLocator.ForClassLoader.read(INTERCEPTOR_CLASS)));
}
}

public final class TimeShiftedSystem {
private TimeShiftedSystem() {}

@Advice.OnMethodExit
public static long nanoTime(@Advice.Return long originalReturnValue) {
System.out.println("originalReturnValue = " + originalReturnValue);

return originalReturnValue - 1000;
}
}

但这失败了:

[Byte Buddy] DISCOVERY java.lang.System [null, module java.base, loaded=true]
[Byte Buddy] ERROR java.lang.System [null, module java.base, loaded=true]
java.lang.IllegalStateException: Cannot call super (or default) method for public static native long java.lang.System.nanoTime()
at net.bytebuddy.implementation.SuperMethodCall$Appender.apply(SuperMethodCall.java:133)

有什么办法可以实现吗?我尝试过的其他东西:

  • 使用 MethodDelegation.to而不是 Advice.to然后调用System.nanoTime()里面TimeShiftedSystem#nanoTime() - 这似乎是第一次调用原始 nanoTime,但立即进入计算器溢出。
  • 使用 MethodDelegation.to而不是 Advice.to@Origin Method method作为参数。似乎根本不会被调用(如果还使用了 @RuntimeType 注释则不会被调用)。
  • 使用 enabledNativeMethodPrefix("native") - 什么都不做。

非常感谢任何帮助。

最佳答案

解决方案是设置

    .with(AgentBuilder.TypeStrategy.Default.REBASE)
.enableNativeMethodPrefix("native")

关于 AgentBuilder而不是 agentBuilder.TypeStrategy.Default.REDEFINE (并将 'Can-Set-Native-Method-Prefix': true 添加到我的 jar list 中)。这让我得到了 TimeShiftedSystem使用此建议:

@Advice.OnMethodExit
public static void nanoTime(@Advice.Return(readOnly = false) long returnValue) {
System.out.println("Called with " + returnValue);
returnValue = 42;
}

关于java - 使用 byte-buddy (System.nanoTime()) 拦截和更改静态本地方法的返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60080688/

25 4 0
文章推荐: reactjs - react 引导:Dropdown.item,onSelect 返回一个空目标
文章推荐: javascript - 使用 javascript 动态更改