java你可能不知道的事(2)--堆和栈

在java语言的学习和使用当中你可能已经了解或者知道堆和栈,但是你可能没有完全的理解它们。今天我们就一起来学习堆、栈的特点以及它们的区别。认识了这个之后,你可能对java有更深的理解。

Java堆内存(Heap Memory)

堆内存在Java运行时主要去回收对象和JRE的类。当我们创建了一个对象(也就是 new一个对象),在堆内存就会为对象分配一个空间,Java垃圾回收器(GC)运行在堆内存里,一旦发现没有任何地方引用到这个对象,就释放这个对象所占的内存。
被创建的对象存在于堆内存,并且拥有全局权限,能被应用的任何地方引用到。

Java栈内存(Stack Memory)

堆内存是单线程执行的,它的空间比堆内存空间要小。它里面会包括定义在方法里的、短时间存在的局部变量,这些局部变量总是引用到堆内存的对象。堆内存还有个特点就是后进先出。当一个方法被调用之后,在栈内存就会为这个方法产生一个内存区域来保存方法里的基本数据类型数据和引用了堆内存中对象的局部变量。当这个方法执行完毕,这个块没有用了,就会被垃圾回收器回收,接着继续下一个方法。

加深理解

先来看一段简单的代码

public class TestMemory {

    public static void main(String[] args) {
        int i = 666;//line1
        Object object = new Object();//line2
        TestMemory testMemory = new TestMemory();//line3
        testMemory.test(object);//line4
    }
//line5
    private void test(Object params){//line6
        String str = params.toString();//line7
        System.out.println(str);//line8
    }
}
//line9

下面这张图片展示了上面代码的内存信息。

这里写图片描述

1、当程序运行时,JVM会先加载运行时的类和我们自己写的类信息,这些类信息加载后存在堆内存当中。

2、接着进入到main方法,第一行line1创建了一个基本数据类型i=666,所以创建了一个main方法的内存块,它里面同时存放了i=666;

3、接着line2和line3的位置
Object object = new Object();
TestMemory testMemory = new TestMemory();创建了两个局部变量,object和testMemory,同时在堆里存放了两个新的对象Object和TestMemory。(每次我们new 一个对象都会在堆区产生一块内存区给它分配空间)。同时object和testMemory引用了new出来的对象。

4、现在到了line4,test方法了,当调用到test方法的时候,在栈的顶层创建了一块test()方法的内存区(我们说过栈的特点就是后进先出),由于在 Java里的传递是值传递,所以就有了参数object产生了一个新的引用。

5、最后调用了toString产生了一个字符串常量存放在了String pool里,并且str 引用了它。(如果你有String类感兴趣,你可能喜欢 》 Java你可能不知道的事系列1_String类

6、当test方法结束,它里面的变量也就被GC回收掉了。接着main方法也就结束。Java在运行时释放这些内存并结束程序的运行。

总结

1、当一个对象被创建,总是会在堆内存为它分配空间并且存储,如果有赋值就会将变量引用到对象。而栈内存就是存放这些引用对象的局部变量。

2、栈内存的生命周期很短,而堆内存从程序执行开始到结束一只都需要工作。因为栈内存没当执行完一个方法,它们所占的内存区就会被释放。而堆内存里的对象只有在没有任何变量引用到它的时候才可能会被释放。

3、栈内存大小相比于堆内存非常小。但是它相对于堆内存又比较快。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Java中,(Heap)和(Stack)是内存管理的重要组成部分,它们各自存储不同类型的数据,并有不同的生命周期和管理策略: 1. **(Stack)**: - **位置**:位于程序运行的最顶层,通常被称为“当前”内存区域,是线程私有的。 - **数据结构**:基于LIFO(Last In First Out)原则,类似于书,新元素添加在顶部,删除也是从顶部开始。 - **内容**:存放局部变量、方法参数和返回地址等信息。每次方法调用,都会为其创建一个新的帧。 - **大小限制**:内存有限,超过限制可能导致溢出异常(StackOverflowError)。 - **生命周期**:当方法结束,帧及其包含的所有变量都将被清除。 2. **(Heap)**: - **位置**:在之下的内存区域,由JVM统一管理和分配。 - **数据结构**:基于动态分配,可以任意增加或减少,不是按照顺序排列的。 - **内容**:主要存放对象实例和数组,全局变量和静态变量也在上。 - **内存分配**:对象在上创建,垃圾回收负责回收不再使用的对象。 - **大小**:相对于来说,内存一般大得多,不会因为局部变量过多而受限。 - **生命周期**:直到对象被显式地设置为null或垃圾回收标记为不再引用,内存才被释放。 总结来说,用于存储程序的临时数据,对资源有严格的限制且易于管理;则用于长期保存对象实例,容量大但管理相对复杂。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员yqy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值