java - 更改 JIT 编译的最终值

标签 java reflection

我注意到一件非常奇怪的事情,即在通过反射更改最终字段后,返回该字段的方法始终给出旧值。我想这可能是因为 JIT 编译器。

示例程序如下:

public class Main
{
private static final Main m = new Main();
public static Main getM()
{
    return m;
}

public static void main(String args[]) throws Exception
{
    Main m = getM();
    int x = 0;
    for(int i = 0;i<10000000;i++)
    {
        if(getM().equals(m))
            x ++;
    }
    Field f = Main.class.getDeclaredField("m");
    f.setAccessible(true);
    removeFinal(f);
    Main main1 = new Main();
    f.set(null, main1);
    Main main2 = (Main) f.get(null);
    Main main3 = getM();
    System.out.println(main1.toString());
    System.out.println(main2.toString());
    System.out.println(main3.toString());
}

private static void removeFinal(Field field) throws NoSuchFieldException, IllegalAccessException
{
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
}
}

结果是:

Main@1be6f5c3
Main@1be6f5c3
Main@6b884d57

我想知道,如何让 getM() 返回更新后的值?

最佳答案

I am wondering, how can i make getM() return updated value?

在 final 中,你不能。返回“旧”值是合法行为,如 JLS 17.5.3 :

Even then, there are a number of complications. 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.

Another problem is that the specification allows aggressive optimization of final fields. Within a thread, it is permissible to reorder reads of a final field with those modifications of a final field that do not take place in the constructor.

请参阅该章中包含的指导性示例。

克服此规定的尝试必须包括在堆栈中扰乱优化器,并且充其量是脆弱的。如果您选择修改字段,那么根据定义,这些字段不应该是最终的。如果您出于性能原因想要这样做(真的吗?),那么 JSR 292 提供了执行 "almost final" 的机制。 build 。

关于java - 更改 JIT 编译的最终值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34829470/

相关文章:

go - 使用反射更新结构字段

c# - 基于 c# 中的用户输入解析为原始类型

java - 线程中出现异常 "main"java.lang.UnsatisfiedLinkError : no JNTIest in java. library.path

java - Sili压缩器未压缩从Android中的图库中拾取的视频

java - clone() 方法如何访问对象的字段? ( java )

java - 在 Java 中使用泛型时出现空指针异常

c# - 迭代变量和查找特定类型实例的技术

java.lang.ClassNotFoundException : org. glassfish.jersey.servlet.ServletContainer 异常

reflection - 为什么 int32(0) 不是 reflect.DeepEqual 在 Golang 中键入零?

c# - 声明类型的 MethodInfo 相等性