Java中 堆 栈,常量池等概念解析
一、
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.
2. 栈:由编译器自动分配释放,存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
3. 堆:存放所有new出来的对象。
4. 静态域:存放静态成员(static定义的)
5. 常量池:存放字符串常量和基本类型常量(public static final)。
6. 非RAM存储:硬盘等永久存储空间
2. 栈:由编译器自动分配释放,存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
3. 堆:存放所有new出来的对象。
4. 静态域:存放静态成员(static定义的)
5. 常量池:存放字符串常量和基本类型常量(public static final)。
6. 非RAM存储:硬盘等永久存储空间
二、
1.栈
栈中存放基本类型的变量和对象的引用,他们的内存大小和生命周期是确定的,
会在变量退出作用域时有编译器释放所占内存。
2.堆
堆内存用来存放new()出来的对象,尔对象的引用则依然存放在栈中。堆中的内存由Java虚拟机的自动垃圾回收器来管理。当栈内存中不存在堆中的对象的引用时此对象成为垃圾,会在某一时刻被垃圾回收器回收。
3.常量池
常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "java"这种申明方式;当然也可扩充,执行器产生的常量也会放入常量池,故认为常量池是JVM的一块特殊的内存空间。
在Java程序中,有很多的东西是永恒的,不会在运行过程中变化。比如一个类的名字,一个类字段的名字/所属类型,一个类方法的名字/返回类型/参数名与所属类型,一个常量,还有在程序中出现的大量的字面值。
比如下面小段源码中粗体代码显示的部分:
public class
ClassTest {
private
String itemS ="我们 ";
private final
int itemI =100 ;
public void
setItemS (String para ){...}
}
而这些在JVM解释执行程序的时候是非常重要的。那么编译器将源程序编译成class文件后,会用一部分字节分类存储这些粗体代码。而这些字节我们就称为常量池。
如以下代码:
Java代码
- String s1 = "china";
- String s2 = "china";
- String s3 = "china";
- String ss1 = new String("china");
- String ss2 = new String("china");
- String ss3 = new String("china");
这里解释一下黄色这3个箭头,对于通过new产生一个字符串(假设为”china”)时,会先去常量池中查找是否已经有了”china”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”china”对象的拷贝对象。这也就是有道面试题:String s = new String(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。