如果您頻繁存取變數,就需要考慮從何處存取這些變數。變數是 static 變數,還是堆棧變數,或者是類的執行個體變數?變數的儲存位置對存取它的代碼的效能有明顯的影響?例如,請考慮下面這段代碼: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;
}
//存取類的 static 變數
void staticAccess(int val)
{
for (int i=0; i<val; i++)
staticVar += 1;
}
} 這段代碼中的每個方法都執行相同的迴圈,並反覆相同的次數。唯一的不同是每個迴圈使一個不同類型的變數遞增。方法 stackAccess 使一個局部堆棧變數遞增,instanceAccess 使類的一個執行個體變數遞增,而 staticAccess 使類的一個 static 變數遞增。instanceAccess 和 staticAccess 的執行時間基本相同。但是,stackAccess 要快兩到三倍。存取堆棧變數如此快是因為,JVM 存取堆棧變數比它存取 static 變數或類的執行個體變數執行的操作少。JVM 是一種基於堆棧的虛擬機器,因此最佳化了對堆棧資料的存取和處理。所有局部變數都儲存在一個局部變數表中,在 Java 運算元堆棧中進行處理,並可被高效地存取。存取 static 變數和執行個體變數成本更高,因為 JVM 必須使用代價更高的作業碼,並從常數儲存池中存取它們。(常數儲存池儲存一個類型所使用的所有類型、欄位和方法的符號引用。)通常,在第一次從常數儲存池中訪問 static 變數或執行個體變數以後,JVM 將動態更改位元組碼以使用效率更高的作業碼。儘管有這種最佳化,堆棧變數的存取仍然更快。考慮到這些事實,就可以重新構建前面的代碼,以便通過存取堆棧變數而不是執行個體變數或 static 變數使操作更高效。請考慮修改後的代碼:class StackVars
{
//與前面相同...
void instanceAccess(int val)
{
int j = instVar;
for (int i=0; i<val; i++)
j += 1;
instVar = j;
}
void staticAccess(int val)
{
int j = staticVar;
for (int i=0; i<val; i++)
j += 1;
staticVar = j;
}
} 方法 instanceAccess 和 staticAccess 被修改為將它們的執行個體變數或 static 變數複製到局部堆棧變數中。當變數的處理完成以後,其值又被複製回執行個體變數或 static 變數中。這種簡單的更改明顯提高了 instanceAccess 和 staticAccess 的效能。這三個方法的執行時間現在基本相同,instanceAccess 和 staticAccess 的執行速度只比 stackAccess 的執行速度慢大約 4%。這並不表示您應該避免使用 static 變數或執行個體變數。您應該使用對您的設計有意義的儲存機制。例如,如果您在一個迴圈中存取 static 變數或執行個體變數,則您可以臨時將它們儲存在一個局部堆棧變數中,這樣就可以明顯地提高代碼的效能。這將提供最高效的位元組碼指令序列供 JVM 執行。