浅析Java中的栈和堆

Java程序在运行时都要开辟空间,任何软件在运行时都要在内存中开辟空间,Java虚拟机运行时也是要开辟空间的。JVM运行时在内存中开辟一片内存区域,启动时在自己的内存区域中进行更细致的划分,因为虚拟机中每一片内存处理的方式都不同,所以要单独进行管理。(JDK 1.8 中,已经没有方法区(永久代),而是将方法区直接放在一个与堆不相连的本地内存区域(Native Memory),这个区域被叫做元空间

如下图所示:

这里写图片描述

 栈:栈是一种线性数据结构,遵从 LIFO(后进先出)的操作顺序,所有操作都是在顶部进行

这里写图片描述

栈内存:存储的都是局部变量,凡是定义在方法中的都是局部变量(方法外的是全局变量),for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量,变量有自己的作用域,一旦离开作用域,变量就会被释放。(在函数中定义的一些基本类型的变量(8种)和对象的引用变量都是在函数的栈Stack内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。)栈内存的更新速度很快,因为局部变量的生命周期都很短。存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(int, short, long, byte, float, double, boolean, char)和对象句柄。

   堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性),如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的,但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。堆里的实体虽然不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的收取。(Java 堆是垃圾收集器管理的主要区域,因此也被称作GC堆(Garbage Collected Heap)
举个例子:

class Person {
 
    int age;
 
}
 
 
public class LearnHeap {
 
 
    public static void main(String args[]){
 
        int a=10;
        Person person = new Person();
        person.age =20;
 
        change(a,person);
        System.out.println("a="+ a+",and person.age = "+person.age);
 
    }
 
    static void change(int a1, Person person){
 
        a1 = 11;
        person.age= 21;
        System.out.println("a1="+ a1+",and age1 = "+person);
 
    }
 
}

以上程序内存加载的执行步骤:

第1步 —— main()函数是程序入口,JVM先执行,首先将main方法压入栈中,在栈内存中开辟一个空间,存放int类型变量a,同时附值10。
      在堆中分配一片区域,用来存放和创建Person对象,这片内存区域会有属于自己的内存地址,假设是1001,然后给成员变量赋值,age=20
      执行结束后,构造防范弾栈,Person创建完成,将Person的内存地址1001赋值给person(此处person小写,是引用变量类型)

第2步 —— JVM执行change()函数,在栈内存中又开辟一个新的空间,存放int类型变量a和对象Person中person
     此时main空间与change空间并存,同时运行,互不影响。

第3步 —— change()方法执行,将a赋值为11,person对象的堆中年龄age赋值为21

第4步 —— change()执行完毕,变量a立即释放,空间消失。但是main()函数空间仍存在,main中的变量a仍然存在,不受影响。而person在堆中对应的地址,所指的age已经赋值=21

总结:

堆与栈的区别很明显:

            1.栈内存存储的是局部变量而堆内存存储的是实体;

            2.栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;

            3.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收

            4.栈内存中的数据,没有默认初始化值,需要手动设置。

            5.堆内存中所有的实体都有内存地址值。

拓展


成员变量与局部变量

成员变量 : 方法外部,类内部定义的变量;

局部变量 : 方法或语句块内部定义的变量,必须初始化。

形参是局部变量,实参则可能是方法中的局部变量或全局变量。
栈内存中的局部变量随方法而生,随方法而灭。
成员变量存储在堆中的对象里,由垃圾收集器回收。

参考文章:java内存区域——堆,栈,方法区等

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chen_ShengJie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值