Java 栈内存与堆内存分配机制详解

在 Java 中,内存分配主要分为两大类,即栈内存堆内存。它们各有用途,并且具备不同的特性。

  • 栈内存: 用于在程序执行期间存储基本类型的局部变量、方法调用信息以及对象的引用。
  • 堆内存: 用于存储实际的对象以及在运行时分配的动态数据。使用 new 关键字创建的对象都存放在这里,该区域的内存由垃圾回收器进行管理。

Java


CODEBLOCK_3497a14d

输出结果

Employee ID: 101
Name: Maddy
Salary: 50000.0
Employee ID: 102
Name: Maddy
Salary: 60000.0

上述示例的内存表示图:

!stack内存表示图

  • emp1 和 emp2: 引用存储在栈上。
  • new Employee(…): 对象存储在堆中。
  • "Maddy": 在字符串常量池(堆)中只存储一次。
  • emp1.name 和 emp2.name: 都指向同一个字符串对象。
  • display(emp1): 创建一个新的栈帧,参数 e 指向 emp1。
  • (emp1.name == emp2.name): 结果为 true,因为它们引用的是同一个池化字符串。

栈内存分配

栈内存用于方法调用、局部变量和引用的存储。当方法启动时,内存会自动分配;当方法结束时,内存会自动清除。数据仅在方法执行期间存在。如果栈空间耗尽,就会发生 StackOverflowError(栈溢出错误)。

Java


CODEBLOCK_1d7a8181

输出结果

The sum is: 30

堆内存用于存储使用 new 关键字创建的对象和实例变量。其大小取决于类的结构。垃圾回收器通过移除未使用的对象来管理这一区域。

堆内存区域划分:

  • 年轻代: 存储新创建的对象。
  • 幸存区: 保存从 Eden 区经过垃圾回收后仍然存活的对象。
  • 老年代: 存储生命周期较长的对象。

非堆内存区域:

  • 元空间: 存储类的元数据,并使用本地内存(在 Java 8 中引入,替代了永久代)。
  • 代码缓存: 存储经过 JIT 编译和优化的本地代码。

示例: 堆中的对象

Java


CODEBLOCK_3bf99098

在这里,INLINECODEb66ed043 对象位于堆中,而引用变量 INLINECODE56670477 位于栈中。

> 注意: 堆中的垃圾回收机制确保了内存的自动管理。

Java 中栈内存与堆内存的区别

栈内存

堆内存

内存以连续块的形式分配。

内存以任意随机顺序分配。

分配和释放是自动的(由编译器处理)。

分配和释放是自动的(由垃圾回收器处理)。

成本较低

成本较高

实现较为简单

实现较为复杂

访问速度较快

访问速度较慢

有限的内存大小可能导致短缺问题。

由于动态分配,可能会遭受内存碎片化的影响。

栈提供了极好的内存局部性

堆的内存局部性尚可,但不如栈高效

线程安全,存储的数据只能被拥有者访问

非线程安全,存储的数据对所有线程可见

栈的大小是固定的

堆可以根据需要进行调整大小

栈使用线性数据结构

堆使用分层(树状)数据结构

数组中首选静态内存分配。

链表中首选堆内存分配。

比堆内存小。

比栈内存大。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/43135.html
点赞
0.00 平均评分 (0% 分数) - 0