更改 JIT 编译的最终值 [英] Change final value compiled by JIT

查看:37
本文介绍了更改 JIT 编译的最终值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I noticed a very strange thing that after changing final field via Reflection, method returning that field is all the time giving old value. I suppose this might be because of JIT compiler.

这是示例程序:

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?

推荐答案

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

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

对于决赛,你不能.返回旧"值是一种合法行为,如 JLS17.5.3:

With finals, you can't. Returning "old" value is a legitimate behavior, as JLS 17.5.3:

即便如此,仍有许多并发症.如果最后一个字段是初始化为字段中的常量表达式(第 15.28 节)声明,可能不会观察到对最终字段的更改,因为该最终字段的使用在编译时替换为值的常量表达式.

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.

另一个问题是规范允许激进最终字段的优化.在一个线程内,允许使用 final 的那些修改重新排序对 final 字段的读取不会出现在构造函数中的字段.

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.

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

See the instructive example that is included in that chapter.

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

Attempts to overcome this provision would have to include messing with optimizers down the stack, and are fragile at best. If you are choosing to modify fields, then, by definition, those fields should not be final. If you want this for performance reasons (do you, really?), then JSR 292 provides the mechanics to do "almost final" constructions.

这篇关于更改 JIT 编译的最终值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆