全局变量存放在哪里?
看了下深入java虚拟机,有这么几个问题,希望大神们给解决下,1.final、static分别修饰的变量会放到哪里?2.看对栈的描述是局部变量放到栈中,那么全局变量放到哪里?
RednaxelaFX,从事JVM研发
这里只讨论Java/JVM层面的概念。
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).
(其实还有一种特殊的,闭包捕获的变量。那个其实是Java语言层面的语法糖,实际实现会用成员字段来实现,所以不单独讲了)
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
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.
而同样从JVM规范层面看,Java的局部变量与参数则存放在JVM栈上:
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里了)。