JAVA中的数据存储(堆及堆栈)

转自:http://www.iteye.com/topic/634530
1.寄存器:最快的存储区, 由编译器根据需求进行分配,咱们在程序中没法控制.
2. 栈:存放基本类型的变量数据和对象的引用,但对象自己不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(对象可能在常量池里)(字符串常量对象存放在常量池中。)
3. 堆:存放全部new出来的对象。
4. 静态域:存放静态成员(static定义的)
5. 常量池:存放字符串常量和基本类型常量(public static final)。有时,在嵌入式系统中,常量自己会和其余部分分割离开(因为版权等其余缘由),因此在这种状况下,能够选择将其放在ROM中 。
6. 非RAM存储:硬盘等永久存储空间

这里咱们主要关心栈,堆和常量池,对于栈和常量池中的对象能够共享,对于堆中的对象不能够共享。栈中的数据大小和生命周期是能够肯定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,所以大小和生命周期不须要肯定,具备很大的灵活性。
对于字符串:其对象的引用都是存储在栈中的,若是是编译期已经建立好(直接用双引号定义的)的就存储在常量池中,若是是运行期(new出来的)才能肯定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份
如如下代码:c++

Java代码  收藏代码
  1. String s1 = "china";  
  2. String s2 = "china";  
  3. String s3 = "china";  
  4. String ss1 = new String("china");  
  5. String ss2 = new String("china");  
  6. String ss3 = new String("china");  



 

这里解释一下黄色这3个箭头,对于经过new产生一个字符串(假设为”china”)时,会先去常量池中查找是否已经有了”china”对象,若是没有则在常量池中建立一个此字符串对象,而后堆中再建立一个常量池中此”china”对象的拷贝对象。这也就是有道面试题:String s = new String(“xyz”);产生几个对象?一个或两个,若是常量池中原来没有”xyz”,就是两个程序员

对于基础类型的变量和常量:变量和引用存储在栈中,常量存储在常量池中。
如如下代码:面试

Java代码  收藏代码
  1. int i1 = 9;  
  2. int i2 = 9;  
  3. int i3 = 9;   
  4. public static final int INT1 = 9;  
  5. public static final int INT2 = 9;  
  6. public static final int INT3 = 9;  




对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。
形式参数是局部变量,局部变量的数据存在于内存中。栈内存中的局部变量随着方法的消失而消失。
成员变量存储在堆中的对象里面,由垃圾回收器负责回收。
注意:栈里只有一个9 ,i1,i2,i3 都指向9 。若是令 i2=7;会在栈里生成7 再令i2 指向7
如如下代码:数组

Java代码  收藏代码
  1. class BirthDate {  
  2.     private int day;  
  3.     private int month;  
  4.     private int year;      
  5.     public BirthDate(int d, int m, int y) {  
  6.         day = d;   
  7.         month = m;   
  8.         year = y;  
  9.     }  
  10.     省略get,set方法………  
  11. }  
  12.   
  13. public class Test{  
  14.     public static void main(String args[]){  
  15. int date = 9;  
  16.         Test test = new Test();        
  17.            test.change(date);   
  18.         BirthDate d1= new BirthDate(7,7,1970);         
  19.     }    
  20.   
  21.     public void change1(int i){  
  22.         i = 1234;  
  23.     }  

}


对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:
1. main方法开始执行:int date = 9;
date局部变量,基础类型,引用和值都存在栈中
2. Test test = new Test();
test为对象引用,存在栈中,对象(new Test())存在堆中
3. test.change(date);
i为局部变量,引用和值存在栈中。当方法change执行完成后,i就会从栈中消失。
4. BirthDate d1= new BirthDate(7,7,1970);  
d1为对象引用,存在栈中,对象(new BirthDate())存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,所以它们的数据也存储在栈中。day,month,year为成员变量,它们存储在堆中(new BirthDate()里面)。当BirthDate构造方法执行完以后,d,m,y将从栈中消失。
5.main方法执行完以后,date变量,test,d1引用将从栈中消失,new Test(),new BirthDate()将等待垃圾回收
------------------------------------------------------------------------------------------------------------------------------
JVM 中的堆栈
JVM是基于堆栈的虚拟机.JVM为每一个新建立的线程都分配一个堆栈.也就是说,对于一个Java程序来讲,它的运行就是经过对堆栈的操做来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操做:以帧为单位的压栈和出栈操做。 
  咱们知道,某个线程正在执行的方法称为此线程的当前方法.咱们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的 Java堆栈里新压入一个帧。这个帧天然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其余数据.这个帧在这里和编译原理中的活动纪录的概念是差很少的. 
  从Java的这种分配机制来看,堆栈又能够这样理解:堆栈(Stack)是操做系统在创建某个进程时或者线程(在支持多线程的操做系统中是线程)为这个线程创建的存储区域,该区域具备先进后出的特性。 
  每个Java应用都惟一对应一个JVM实例,每个实例惟一对应一个堆。应用程序在运行中所建立的全部类实例或数组都放在这个堆中,并由应用全部的线程共享.跟C/C++不一样,Java中分配堆内存是自动初始化的。Java中全部对象的存储空间都是在堆中分配的,可是这个对象的引用倒是在堆栈中分配,也就是说在创建一个对象时从两个地方都分配内存,在堆中分配的内存实际创建这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。

JAVA 堆栈
栈与堆都是Java用来在Ram中存放数据的地方。与C++不一样,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
  Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象经过new、newarray、anewarray和multianewarray等指令创建,它们不须要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优点是能够动态地分配内存大小,生存期也没必要事先告诉编译器,由于它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些再也不使用的数据。但缺点是,因为要在运行时动态分配内存,存取速度较慢。 
  栈的优点是,存取速度比堆要快,仅次于寄存器,栈数据能够共享。但缺点是,存在栈中的数据大小与生存期必须是肯定的,缺少灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。 
  栈有一个很重要的特殊性,就是存在栈中的数据能够共享。假设咱们同时定义: 
  int a = 3; 
  int b = 3; 
  编译器先处理int a = 3;首先它会在栈中建立一个变量为a的引用,而后查找栈中是否有3这个值,若是没找到,就将3存放进来,而后将a指向3。接着处理int b = 3;在建立完b的引用变量后,由于在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的状况。这时,若是再令a=4;那么编译器会从新搜索栈中是否有4值,若是没有,则将4存放进来,并令a指向4;若是已经有了,则直接将a指向这个地址。所以a值的改变不会影响到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不一样的,由于这种状况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另外一个对象引用变量 
----------------------------------------------------------------------------------------------
Java数组存放在哪里?
答:堆内存。
而c++ 里确定是在栈里(C++ 在堆里生成的必定要手动delete 掉本身回收的,而int a[]={1,3}咱们不需手动回收)多线程

相关文章
相关标签/搜索