栈(stack)与堆(heap)
栈:存取速度快,仅次于CPU中的寄存器,栈中的数据大小与生存期是确定的。
堆:存取速度较慢,可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。
堆主要用来存放对象的,栈主要是用来执行程序的
java中的数据与堆、堆栈
JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。
值类型数据在堆栈中,引用类型数据的引用在堆栈中,数据在堆中。
举例说明:String是一个特殊的包装类数据。
可以用:
String str = new String("abc");
String str = "abc";
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。
知识点延伸
在JAVA中,有六个不同的地方可以存储数据:
1. 寄存器(register)。这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部。但是寄存器的数量极其有限,所以寄存器由编译器根据需求进行分配。你不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象。
2. 堆栈(stack)。位于通用RAM中,但通过它的“堆栈指针”可以从处理器哪里获得支持。堆栈指针若向下移动,则分配新的内存;若向上移动,则释放那些 内存。这是一种快速有效的分配存储方法,仅次于寄存器。创建程序时候,JAVA编译器必须知道存储在堆栈内所有数据的确切大小和生命周期,因为它必须生成 相应的代码,以便上下移动堆栈指针。这一约束限制了程序的灵活性,所以虽然某些JAVA数据存储在堆栈中——特别是对象引用,但是JAVA对象不存储其 中。
3. 堆(heap)。一种通用性的内存池(也存在于RAM中),用于存放所以的JAVA对象。堆不同于堆栈的好处是:编译器不需要知道要从堆里分配多少存储区 域,也不必知道存储的数据在堆里存活多长时间。因此,在堆里分配存储有很大的灵活性。当你需要创建一个对象的时候,只需要new写一行简单的代码,当执行 这行代码时,会自动在堆里进行存储分配。当然,为这种灵活性必须要付出相应的代码。用堆进行存储分配比用堆栈进行存储存储需要更多的时间。
4. 静态存储(static storage)。这里的“静态”是指“在固定的位置”。静态存储里存放程序运行时一直存在的数据。你可用关键字static来标识一个对象的特定元素是静态的,但JAVA对象本身从来不会存放在静态存储空间里。
5. 常量存储(constant storage)。常量值通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变。有时,在嵌入式系统中,常量本身会和其他部分分割离开。存在于
6. 非RAM存储。如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。
速度:寄存器 > 堆栈 > 堆 > 其他
延伸举例
1:堆栈(stack)
方法的参数值
public void sun (int a , int b)
局部变量
public static void main(String[] args){ int a = 5; } 、
引用变量
Person p = new Person(“zhaoyue”, 22);
调用构造方法的时候,“形参”先在堆栈中开辟内存,存放“实参”,再把“实参”的一份拷贝传入对象之中。此时,“实参”的拷贝存放在堆(heap)中,构造方法结束堆栈中的内存释放。
堆栈的存储要领:压栈,出栈,自动清除!
2:堆(heap)
成员变量
public class Person{ String name; int age; }
new得到的对象
Person p = new Person(“zhaoyue”, 22);
3:数据区(Data segment)
静态存储(static storage) 静态变量
public static int a = 5;
JVM运行时首先为其开辟空间,位置不变,程序运行结束时空间释放。并且在运行时只加载一次。
静态方法
public static void run() { print(“hello”); }
JVM运行时首先为其开辟空间,位置不变,程序运行结束时空间释放。并且在运行时只加载一次。
常量存储(constant storage) 常量 public final int a = 5;
4:Code segment(代码区)
Code segment 存放代码
方法区(method area) 成员方法
Public void run(){System.out.println(“I’m run!”);}
类装载的时候存储在方法区,初始时被隐藏,实例化对象时被激活。