gpt4 book ai didi

java - 更改 "static final"字段的值

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

假设我有一个

class Foo(){
public final static int bar = -1;
}

反汇编的字节码看起来像这样

super public class Foo
version 51:0
{

public static final Field bar:I = int -1;

public Method "<init>":"()V"
stack 1 locals 1
{
aload_0;
invokespecial Method java/lang/Object."<init>":"()V";
return;

}

} // end Class Foo

是的,这让我很吃惊。我本来希望有一个 <clinit>包含对 bar 的赋值的方法然后我可以更换。 (当我删除 final 修饰符时确实会发生这种情况。)

如何更改 final 的值 field ?我 Hook 什么?

最佳答案

您的期望不正确。用整数文字初始化的 static final int 将是编译时常量。编译时常量由字节码编译器内联。

无法在运行时更改值,也无法使用字节码修改。字节码编译器所做的内联无法展开。重新编译类及其依赖类是更改编译时常量值的唯一易于处理的方法。

请注意,这不仅仅是 Java 编译器实现的一个不方便的产物。这种编译时常量的处理由 JLS 强制执行。例如,JLS 17.5.3 说这是关于尝试使用反射更改编译时常量 final:

"If a final field is initialized to a constant expression (§15.28) in the field declaration, changes to the final field may not be observed, since uses of that final field are replaced at compile time with the value of the constant expression."

换句话说,改变 Foo.bar 的反射 API 调用可能看起来成功了,但内联的实际值并没有改变。事实上,唯一可能看到更新值的代码是使用反射读取 Foo.bar 的代码!

一个可能的解决方法是以一种使其不是编译时常量的方式声明常量。例如:

class Foo() {
public final static int bar = Integer.parseInt("-1");
}

关于java - 更改 "static final"字段的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48768159/

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