Java/JVM的抽象概念里沒有“全局變量”這種概念。
如果一個JVM是用C/C++實現的,那么在實現層里用到的“全局變量”就放在實現語言的全局變量所存儲的位置,跟Java/JVM自身沒關系。
題主說的“全局變量”多半實際想問的是Java層面的“靜態變量”。下面再說。
在Java層面上,變量的存儲種類(storage class)可以粗略分為3種:
- 局部變量/方法參數,在方法體中/參數列表中聲明,操作的Java字節碼為xload / xstore / iinc
- 成員字段,在類中聲明,操作的Java字節碼為getfield / putfield。
- A field that is not declared static (sometimes called a non-static field) is called an instance variable. Whenever a new instance of a class is created (§12.5), a new variable associated with that instance is created for every instance variable declared in that class or any of its superclasses.
- 靜態變量,在類中聲明,操作的Java字節碼為getstatic / putstatic。
- If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized (§12.4).
static在Java里是一種storage modifier(存儲修飾符),它會影響變量的存儲種類;
final在Java里則不是一種存儲修飾符,不影響變量的存儲種類。
所以,被final修飾的變量,該存哪兒存哪兒,跟final與否根本沒關系;
被static修飾的變量是靜態變量,從JVM規范層面看,它會存儲在“方法區”(method area)這個運行時數據區里。
Chapter 2. The Structure of the Java Virtual Machine
2.5.4. Method Area而同樣從JVM規范層面看,Java的局部變量與參數則存放在JVM棧上:
The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the "text" segment in an operating system process. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization.
2.5.2. Java Virtual Machine Stacks
Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local variables and partial results, and plays a part in method invocation and return. Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does not need to be contiguous.
“方法區”是JVM規范所描述的抽象概念。在實際的JVM實現中,它不一定是由單一的特殊區域所實現。
舉例來說,作為一種JVM實現,HotSpot VM的不同版本就會把靜態變量放在不同的地方。
在Sun JDK6 / OpenJDK6或以前的HotSpot VM里,靜態變量存儲在instanceKlass對象的末尾,而instanceKlass對象存儲在一個由GC管理的、名為Permanent Generation的區域中。請參考傳送門: http://www.valleytalk.org/wp-content/uploads/2011/05/Java_Program_in_Action_20110727.pdf,第121頁
<- 這個做法跟 @代碼豆 大大提到的CLR把靜態變量放在MethodTable對象里是一個思路。
在Oracle JDK7 / OpenJDK7及之后的HotSpot VM里,靜態變量存儲在java.lang.Class對象末尾的隱藏字段里,而java.lang.Class對象存儲在普通的Java heap里(不在PermGen里了)。