在 Java 中,變量的存儲位置直接影響存取速度。通過字節碼分析可以發現:局部變量(棧變量)存取速度比實例變量和靜態變量快 2-3 倍。
class StackVars {
private int instVar; // 實例變量
private static int staticVar; // 靜態變量
// 存取局部變量
void stackAccess(int val) {
int j = 0;
for (int i = 0; i < val; i++) {
j += 1;
}
}
// 存取實例變量
void instanceAccess(int val) {
for (int i = 0; i < val; i++) {
instVar += 1;
}
}
// 存取靜態變量
void staticAccess(int val) {
for (int i = 0; i < val; i++) {
staticVar += 1;
}
}
}
Method void stackAccess(int)
0 iconst_0 // 壓入 0
1 istore_2 // 存入局部變量表索引 2 (j)
2 iconst_0 // 壓入 0
3 istore_3 // 存入局部變量表索引 3 (i)
4 goto 13 // 跳轉到條件檢查
7 iinc 2 1 // 直接增加索引 2 處的值 (j++)
10 iinc 3 1 // 直接增加索引 3 處的值 (i++)
13 iload_3 // 載入 i
14 iload_1 // 載入參數 val
15 if_icmplt 7 // 比較並條件跳轉
18 return
Method void instanceAccess(int)
0 iconst_0
1 istore_2
2 goto 18
5 aload_0 // 載入 this 引用
6 dup // 複製 this
7 getfield #19 // 讀取實例字段 instVar
10 iconst_1
11 iadd // 相加
12 putfield #19 // 寫回實例字段
15 iinc 2 1
// ... 更多指令
| 變量類型 | 存取指令 | 操作步驟 | 相對性能 |
|---|---|---|---|
| 局部變量 | iload/istore, iinc | 直接操作棧幀局部變量表 | 最快 (基準) |
| 實例變量 | aload, getfield/putfield | 需解引用 this,再訪問堆內存 | 慢 2-3 倍 |
| 靜態變量 | getstatic/putstatic | 訪問方法區靜態字段 | 慢 2-3 倍 |
// 低效
for (int i = 0; i < n; i++) {
this.counter++;
}
// 高效
int local = this.counter;
for (int i = 0; i < n; i++) {
local++;
}
this.counter = local;
記住:局部變量存儲在線程私有的棧幀中,無需同步、無緩存一致性開銷、指令最精簡。這是 Java 性能調優中最容易實施且效果顯著的技巧之一。