说明:JDK源码版本为 Oracle JDK 8
1. 背景
阅读 java.lang.String
的源码,会发现有些地方注释为/* avoid getfield opcode */
,此处的代码是将当前类定义的成员变量引用为本地变量,从字面意思理解,是为了避免使用 getfield 操作码
,那什么是getfield
呢?
2. 实践
《深入理解java虚拟机》这本书中有解释,getfield
是获取指定类的实例域,并将其值压入栈顶
,那么是否意味着每次获取成员变量,都会做一次getfield
操作呢?带着这个疑问,我们写代码验证一下。
创建一个GetField
类,添加代码如下
public class GetFieldTest {
int[] arr = new int[10];
public static void main(String[] args) {
GetFieldTest th = new GetFieldTest();
th.testArr();
}
void testArr() {
arr[0] = 1;
arr[1] = 2;
System.out.println(arr.length);
System.out.println(arr[0]);
System.out.println(arr[1]);
}
}
用javac
命令编译类,并用java
命令运行代码结果:
然后用javap -c
命令反汇编GetField.java
的class
文件:
可以看到,testArr
方法中总共出现了5次getfield
操作码,分别对应每次使用到arr
的行。那么,将arr
引用为方法中的本地变量呢?
修改代码如下:
public class GetFieldTest {
int[] arr = new int[10];
public static void main(String[] args) {
GetFieldTest th = new GetFieldTest();
th.testArr();
}
void testArr() {
int[] arr1 = arr;
arr1[0] = 1;
arr1[1] = 2;
System.out.println(arr1.length);
System.out.println(arr1[0]);
System.out.println(arr1[1]);
}
}
同样反汇编查看getfield
的次数,发现只有一次了:
看来,在方法中频繁使用成员变量时,将其引用为本地变量确实可以减少getfield
操作的次数,也就达到了avoid getfield opcode
的效果,这样也可以提升性能。
参考
[1] CSDN: String源码中的“avoid getfield opcode”是什么意思