1. final 的内存语义

  1. 在构造函数内对一个 final 域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。也就是说只有将对象实例化完成后,才能将对象引用赋值给变量。
  2. 初次读一个包含 final 域的对象的引用,与随后初次读这个 final 域,这两个操作之间不能重排序。也就是下面示例的 4 和 5 不能重排序。
  3. 当 final 域为引用类型时,在构造函数内对一个 final 引用的对象的成员域的写入,与随后在构造函数外把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。

下面通过代码在说明一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class FinalExample {
int i; // 普通变量
final int j; // final变量
static FinalExample obj;

public FinalExample() { // 构造函数
i = 1;// 写普通域
j = 2;// 写final域
}

public static void writer() { // 写线程A执行
// 这一步实际上有三个指令,如下:
// memory = allocate();  // 1:分配对象的内存空间
// ctorInstance(memory); // 2:初始化对象
// instance = memory;  // 3:设置instance指向刚分配的内存地址
obj = new FinalExample();
}

public static void reader() { // 读线程B执行
FinalExample object = obj; // 4\. 读对象引用
int a = object.i; // 5\. 读普通域
int b = object.j; // 读final域
}
}

2. final 语义在处理器中的实现

  • 会要求编译器在 final 域的写之后,构造函数 return 之前插入一个 StoreStore 障屏。
  • 读 final 域的重排序规则要求编译器在读 final 域的操作前面插入一个 LoadLoad 屏障。

3. 内联优化

https://juejin.cn/post/7107909896804237319#heading-1

我们先看直接声明就初始化这种情况:

1
2
3
4
5
6
7
class A {
   private final static int a = 7;
   public static int getA() {
       return a;
  }
}
复制代码

编译再反编译一下:

1
2
3
4
# 我的文件名是Demo.java
javac Demo.java
javap -p -v -c A
复制代码

可以看到这个 getA() 的反编译结果,编译器已经知道了 a=7,并且由于它是一个 final 变量,不会变,所以直接写死编译进去了。相当于直接把 return a 替换成了 return 7

1
2
3
4
5
6
7
8
9
10
11
  public static int getA();
  descriptor: ()I
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
     stack=1, locals=0, args_size=0
        0: bipush        7
        2: ireturn
    LineNumberTable:
      line 21: 0

复制代码

这其实是一个编译器的优化,专业的称呼叫“内联优化”。其实不只是 final 变量会被内联优化。一个方法也有可能被内联优化,特别是热点方法。JIT 大部分的优化都是在内联的基础上进行的,方法内联是即时编译器中非常重要的一环。

一般来说,内联的方法越多,生成代码的执行效率越高。但是对于即时编译器来说,内联的方法越多,编译时间也就越长,程序达到峰值性能的时刻也就比较晚。有一些参数可以控制方法是否被内联:

回到最开始的问题,这种能被编译器内联优化的 final 变量,是会在编译成字节码的时候,就赋值了,所以在类加载的准备阶段,不会给这个变量初始化为默认值。

4. 与 static 搭配使用

static final 用来修饰成员变量和成员方法,可简单理解为“全局常量”!
对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
对于方法,表示不可覆盖,并且可以通过类名直接访问。

5. 参考与感谢

https://www.jianshu.com/p/e6cda45d58d0

内联优化
https://juejin.cn/post/7107909896804237319#heading-1