gpt4 book ai didi

java - 我们可以在类加载后重新转换类吗?

转载 作者:行者123 更新时间:2023-11-30 07:11:39 25 4
gpt4 key购买 nike

我们目前使用 premain 在加载所有类之前对其进行转换。但我们希望控制转换,这意味着我们可以删除/重新添加在方法中插入的代码。

所以我们找到了重新转换,但我不太理解它。

  1. 我们可以重新转换加载的类吗?
  2. 如果可以做到,重新转换的类的实例是否会运行重新转换的代码?
  3. 如果做不到,是否有任何技术可以在运行时更改某些指定方法的代码。
<小时/>

已更新

例如,我们有类 A。类 A 有两个方法 foo() 和 bar():

void foo() {
while(true) {
bar();
}
}
void bar() {
System.out.println("a");
}

我们调用 Instrument.retransformClasses(A.class)。并将 bar() 更改为:

void bar() {
System.out.println("b");
}

如果有一个线程已经在调用 foo(),我们可以得到输出:

...
a
a
a
b
b
b
...

如果没有,有什么办法可以实现吗?

最佳答案

因此,您已经有了一个 ClassFileTransformer 来在类的字节码加载并安装到 JVM 之前对其进行转换。现在您希望沿着 JVM 生命周期再次重新转换,不是吗?

嗯,重新转换可以通过Instrumentation来完成,通过Instrumentation.retransformClasses方法。但首先,您必须通过调用Instrumentation.isRetransformClassesSupported来确保支持重新转换。 .

这次改造什么时候生效?根据javadoc:

If a retransformed method has active stack frames, those active frames continue to run the bytecodes of the original method. The retransformed method will be used on new invokes.

这意味着,在您的示例中,foo() 重复调用bar()。如果同时重新转换bar,则转换后的代码将影响调用bar的下一次迭代。

我将为您的示例添加更多复杂性:

void foo() {
while(true) {
bar();
}
}

void bar() {
myRetransform();
System.out.println("a");
}

void myRetransform() {
// This is where a retransformation of class A, method bar, is triggered.
}

当触发重新转换时,当前栈帧为:

  • myRetransform
  • 酒吧

有一个 Activity 的调用堆栈帧,其中包含 bar,因此当 myRetransform 返回时,它仍会在 system.out 中打印“a”。

然后,bar 将返回并离开当前堆栈帧,如下所示:

现在是最后一次触发的转换生效的时间。即:在下一次调用 bar 时。

关于java - 我们可以在类加载后重新转换类吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39140148/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com