全局变量存放在哪里?
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里了)。