美文网首页
java内存中数据存储位置

java内存中数据存储位置

作者: 第四风111 | 来源:发表于2018-09-05 09:18 被阅读40次

    java内存分配

    • 寄存器:程序无法控制,读写最快!
    • 栈:存放局部变量和对象的引用值,而对象本身则放在堆中(自动回收),可数据共享。
    • 堆:程序运行期被动态创建,存放在堆中。手动回收或者系统gc回收。
    • 静态域:存放对象中对象的static成员。
    • 常量池:存放常量。

    存储位置

    • 先看一段程序吧:
    int i=5;
    int j=5;
    

    那么这段程序中,内存发生了什么变化呢,首先会开辟一个i的存储区,然后会检查栈中有没有5这个值,如果没有,则保存到栈中,然后让i=5,接着开辟一个j的存储区,检查栈中是否有5,如果有,这直接让j=5。即所谓的栈内数据共享。

    • 再看一段程序
    String s1 = "abc";
    String s2 = new String(“abc”);
    
    1. String s = ”abc“的工作过程可以分为以下几个步骤:
      (1)定义了一个名为"s"的String类型的引用。
      (2)检查在常量池中是否存在值为"abc"的字符串对象;
      (3)如果不存在,则在常量池(字符串池)创建存储进一个值为"abc"的字符串对象。如果已经存在,则跳过这一步工作。
      (4)将对象引用s指向字符串池当中的”abc“对象。
    2. String s = new String(”abc“)的步骤则为:
      (1)定义了一个名为"s"的String类型的引用。
      (2)检查在常量池中是否存在值为"abc"的字符串对象;
      (3)如果不存在,则在常量池(字符串池)存储进一个值为"abc"的字符串对象。如果已经存在,则跳过这一步工作。
      (4)在堆中创建存储一个”abc“字符串对象。
      (5)将对象引用指向堆中的对象。
      这里指的注意的是,采用new的方式,虽然是在堆中存储对象,但是也会在存储之前检查常量池中是否已经含有此对象,如果没有,则会先在常量池创建对象,然后在堆中创建这个对象的”拷贝对象“。这也就是为什么有道面试题:String s = new String(“xyz”);产生几个对象?的答案是:一个或两个的原因。因为如果常量池中原来没有”xyz”,就是两个。
    • 最后,借助网上看到的一个例子帮助对栈内存,堆内存的存储进行理解:
    class BirthDate {    
           private int day;    
           private int month;    
           private int year;        
           public BirthDate(int d, int m, int y) {    
               day = d;     
               month = m;     
               year = y;    
           }    
           省略get,set方法………    
       }    
           
       public class Test{    
           public static void main(String args[]){    
                int date = 9;    
                Test test = new Test();          
                test.change(date);     
                BirthDate d1= new BirthDate(7,7,1970);           
           }      
           
           public void change1(int i){    
               i = 1234;    
           }    
    
    • 对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:
    • main方法开始执行:int date = 9; date局部变量,基础类型,引用和值都存在栈中。
    • Test test = new Test(); test为对象引用,存在栈中,对象(new Test())存在堆中。
    • test.change(date); 调用change(int i)方法,i为局部变量,引用和值- 存在栈中。当方法change执行完成后,i就会从栈中消失。
    • BirthDate d1= new BirthDate(7,7,1970);调用BIrthDate类的构造函数生成对象。d1为对象引用,存在栈中;
    • 对象(new BirthDate())存在堆中;其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中;day,month,year为BirthDate对象的的成员变量,它们存储在堆中存储的new BirthDate()对象里面;
    • 当BirthDate构造方法执行完之后,d,m,y将从栈中消失。
    • main方法执行完之后。date变量,test,d1引用将从栈中消失,new Test(),new BirthDate()将等待垃圾回收器进行回收。
      参考文章:https://blog.csdn.net/qq_36838191/article/details/80248182

    相关文章

      网友评论

          本文标题:java内存中数据存储位置

          本文链接:https://www.haomeiwen.com/subject/xpmowftx.html