Jvm内存分配举例
JVM内存分配举例
我们从变量的作用域角度去分析这个问题。
- 按作用域划分变量
- 局部变量
- 全局变量(又叫成员变量)
- 类变量(静态变量)
- 实例变量
局部变量
在方法中声明的变量,即该变量是局部变量,每当程序调用方法时,系统都会为该方法建立一个方法栈,其所在方法中声明的变量就放在方法栈中,当方法结束系统会释放方法栈,其对应在该方法中声明的变量随着栈的销毁而结束,这就局部变量只能在方法中有效的原因。
在方法中生明的变量可以是基本类型的变量,也可以是引用类型的变量
(1)当声明是基本类型变量的时,其变量名及值(变量名及值是两个概念)是放在方法栈中
(2)当声明的是引用变量时,所声明的变量(该变量实际上是在方法中存储的是内存地址值)是放在方法的栈中,该变量所指向的对象是放在堆内存中的,如果该变量所指向的是字面量就放到方法区的运行时常量池中
全局变量
在类中声明的变量是成员变量,也叫全局变量,放在堆中的。
同样在类中声明的变量即可是基本类型变量 也可是引用类型变量
(1)当声明的是基本类型变量且:
(1.1) 如果被static修饰为静态变量,其变量名和变量值放在方法区(no-heap)中
(1.2)如果是实例变量,其变量名及变量值一般放在堆内存中
(2)当声明的是引用类型变量且:
(2.1) 如果被static修饰为静态变量,声明的变量放在方法区中,该变量所指向的对象在堆中,如果变量所指向的对象是字面量就放在方法区的运行时常量池中
(2.2) 如果是实例变量,声明的变量放在堆中,该变量所指向的对象在堆中的另一个地方,如果变量所指向的对象是字面量就放在方法区的运行时常量池中
总结:其实就是注意两点,1)new 出来的对象在堆中;2)静态变量在方法区中;3)字面量在方法区的运行时常量池中;4)基本数据类型没有引用的概念
举例:
// 局部变量
(1)
public void m1() {
int i = 1; // i,1在栈中
}
// 局部变量
(2)
public void m1() {
Object i = new Object(); // i在栈中,new Object()在堆中
String s = "hello"; // s在栈中,"hello"在常量池中
String s1 = new String("hello"); // s1在栈中,new String("hello")在堆中
}
// 全局变量
(1.1)
public Class C {
static int i = 1; // i也是在方法区中, 1也在方法区中
}
(1.2)
public Class C {
int i = 1; // i,1在堆内存中
Object i = new Object(); // i在堆中,new Object()在堆中
String s = "hello"; // s在堆中,"hello"在常量池中
}
(2.1)
public Class C {
static Object i = new Object(); // i方法区中,new Object()在堆中
static String s = "hello"; // s在方法区中,"hello"在方法区的运行时常量池中
}
(2.2)
public Class C {
Object i = new Object(); // i在堆中, new Object()在堆中
String s = "hello"; // s在堆中,"hello"在方法区的运行时常量池中
}
参考
static allocation in java - heap, stack and permanent generation
Java Stack and Heap: Java Memory Allocation Tutorial