内存管理中的堆和栈

一、前提:

    最近在学习马士兵J2SE视频教程,其中第三章面向对象中涉及到了内存管理,马老师多次强调,谁掌握了内存,谁就理解了一起。由此可见,内存管理的重要性。在此做一些总结。本人纯属小白,还望大神多多指导。

    先介绍一下Java的一些基本概念: 首先是成员变量:成员变量可以是Java语言中任何一种数据类型(包括基本类型和引用类型);在定义成员变量时可以对其初始化;成员变量的作用范围整个类体

    引用: Java语言汇总除基础类型(int、float、bool等)之外的变量类型都称之为引用类型,Java中的对象是通过引用对其操作的。如果不对引用类型的成员变量进行初始化,则默认为null。引用类型占两块内存,而基础类型占一块内存。


二、内存管理:

    1、如何在内存中区分类和对象?

    类是静态的概念,代码区对象是new出来的,位于堆内存,类的每个成员变量在不同的对象中都有不同的值(静态变量除外),而方法只有一份,执行的时候才调用。

    2、在内存管理中,一般将内存分为四个区:栈区、堆区、代码区、数据区、                     

      ①栈区(Stack):由编译器自动分配释放,存放函数的参数值局部变量的值等。

      ②堆区(heap):一般由程序员释放,或由垃圾回收机制自动回收。new申请的内存位于此区,new出来的东西放在此区(new出来的是对象)。

      ③全局区(静态区)(Static):全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。

      ④文字常量区:常量字符串就是放在这里。程序结束后由系统释放。

      ⑤代码区:代码区也叫方法区。存放函数体的二进制代码。

三、举例说明:

1、代码如下:

 

<span style="font-family:KaiTi_GB2312;font-size:24px;">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;
    }
    
    public void setDay(int d) {
    	day = d;
  	}
  	
    public void setMonth(int m) {
    	month = m;
    }
    
    public void setYear(int y) {
    	year = y;
    }
    
    public int getDay() {
    	return day;
    }
    
    public int getMonth() {
    	return month;
    }
    
    public int getYear() {
    	return year;
    }
    
    public void display() {
    	System.out.println
        (day + " - " + month + " - " + year);
    }
}


public class Test{
    public static void main(String args[]){
        Test test = new Test();
        int date = 9;
        BirthDate d1= new BirthDate(7,7,1970);
        BirthDate d2= new BirthDate(1,1,2000);    
        test.change1(date);
        test.change2(d1);
        test.change3(d2);
        System.out.println("date=" + date);
        d1.display();
        d2.display();
    }
    
    public void change1(int i){
    	i = 1234;
    }
    
    public void change2(BirthDate b) {
    	b = new BirthDate(22,2,2004);
    }
    
    public void change3(BirthDate b) {
    	b.setDay(22);
    }
}
</span>

    当我们分析程序时,我们应该从main方法的第一句话开始分析。在本例中为Test  test  =  new  Test();是调用了构造方法。此时内存如下:                                           

    第二句话:int  date = 9,在栈区中开辟一块内存。存放变量date,初始值为9。第三句话 BirthDate d1= new BirthDate(7,7,1970),都调用了BirthDate()方法。它有三个形参,需要在栈区中分配三块内存。此时内存如下:                                       

    当调用方法完毕之后,为这个方法分配的所有的局部变量自动消失。此时内存的布局如下图所示。d2的过程也是如此。详细过程不再展示。                                              

    当执行 test.change1(date)语句时,需要调用 change1方法,当方法开始执行时,需要为参数i分配内存空间。此时内存如下,同理方法结束之后,i的空间自动消失。                   

                      

    当执行test.change2(d1)的时候,又需要在栈中分配出一个一个局部变量b,在堆中分配一块区域。方法执行完毕后,局部变量b消失。在某一个时间,垃圾收集机制会回收刚刚分配的堆区。(一般没有引用指向它的时候,垃圾收集机制会回收它)。


    当执行test.change3(d2)方法完成后,此时内存布局如下。                                           



四、总结:

    一定要把内存的执行过程弄懂,整个程序执行的过程将非常明白。关于程序执行过程中内存变化还有好多需要研究的。本文仅仅是起到抛砖引玉的作用。



                                           






        

         


      



评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值