Java中的堆和栈

这篇具有很好参考价值的文章主要介绍了Java中的堆和栈。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

Java数据类型在执行过程中存储在两种不同形式的内存中:栈和堆,它们通常由运行Java虚拟机(JVM)的底层平台维护。本文从Java软件开发的角度提供了对这两种内存类型的一些见解。

Java程序是怎么运行的

Java程序运行在Java Virtual Machine (JVM)中,JVM提供了Java应用程序在运行时所需要的任何资源的管理器。这就意味着开发者写的应用程序或者创建的应用程序没有能力去直接获取系统资源(不管是硬件还是软件),除非JVM能提供给这些资源。所以在Java中,程序运行顺序如下图:

Java中的堆和栈

JVM层使得Java平台能够独立运行,其他编程语言,例如C/C++没有使用类似JVM层的东西,因此它们不是跨平台的语言,即使它们是可移植的语言。它们就像下图一样:

Java中的堆和栈

这两种形式有优点也有缺点,Java已经有了自己的生态系统。与此同时,像C/C++这样的编程语言能够直接访问系统资源,从而更有利于优化核心单元的使用,从而产生超级快速和高效的程序。但两者在软件开发领域都有各自的用途。

所有编程语言在编译和执行过程中都有许多相似之处。其中最重要的一点就是内存管理,无论使用哪种语言,内存管理对程序的整体效率都有重要影响,因为管理好内存资源,从而才能管理好应用程序性能。

Java中的运行内存

应用程序之间的一个常见现象是,每个应用程序都需要一些内存才能以最佳方式工作,该内存由底层平台提供。在Java中,JVM提供了这些内存资源(当然需要操作系统授权)。Java中,JVM内存主要分为5个部分分别为:方法区、堆、栈、PC寄存器和本地方法区。

本文主要关注堆和栈。内存不像一张白纸,程序员只需要草草记下就可以存储数据,在使用内存之前,需要对其进行结构化。栈和堆是使用内存时遵循的数据结构,在程序执行期间,存储的数据用于各种目的,这取决于程序的目的是什么。

JVM决定程序执行期间使用的运行时数据区域。有些数据区域是依赖于JVM的,这意味着它们是在JVM启动时创建的,并在JVM的整个生命周期中持续存在。但是,每个线程都创建和销毁其他数据区域。JVM可以同时执行多个执行线程,这意味着每个线程都有自己的pc(Program Counter,程序计数器)来维护正在执行的当前指令的位置,还有一个栈帧来保存静态内存分配。

栈是内存中的一种结构,开发人员在其中存储元素,其方式允许只从栈顶检索数据——通常称为先入后出(FILO或LIFO)。因为每个线程都维护一个私有的JVM栈,它被用来存储与它们的静态内存分配相关的变量。特定于我们在代码中声明和使用的方法的原语变量实际上存储在栈区域中。另外,对实际存储在堆内存中的对象的引用也存储在堆栈区域中。因此,任何本地分配的内存都存储在堆栈中。

堆栈内存的默认大小可以使用JVM参数-Xss来更改。有时,如果分配了太多变量或方法递归调用自身,则堆栈可能溢出。所有Java程序员都知道的一个常见错误是Java.lang.stackoverflowerror,当栈内存不足时提示该错误。Java中的每个方法调用都会在栈中分配一块内存,因此,设计糟糕的递归方法调用很容易占用所有栈内存,导致栈内存溢出错误。

堆是JVM一启动就创建的内存区域,它会一直存在,直到JVM被销毁。与栈不同的是,栈是单个线程的属性(因为每个线程都有自己的栈),堆实际上是由JVM本身管理的全局内存,此内存在运行时用于为对象分配内存。因此,对象的实例化可以是用户定义的类、JDK或其他库类。简而言之,使用new关键字创建的任何对象都存储在堆内存中。堆内存中的对象可被JVM运行的所有线程访问。访问管理非常复杂,使用了非常复杂的算法,这就是JVM垃圾收集器发挥作用的地方。

堆的默认大小可以使用JVM参数-Xms-Xmx来更改。随着对象的创建和销毁,堆的大小也会增加或减少,如果达到最大内存限制后并尝试进一步分配内存,则抛出java.lang.OutOfMemoryError

堆中的字符串池(StringPool)

Java.lang.String类是Java中使用最多的类,因此,应该特别注意它的效率问题。与基本数据类型相比,字符串的操作效率总是很慢,所以,必须采用某种方式使得字符串对象操作的效率和便利性方面类似或者接近于基本数据类型,为了达到这个目的就在堆中分配了一块特殊内存区域(StringPool),创建的任何字符串对象都由JVM存储在StringPool中。与堆中创建的其他对象相比,这提高了性能。

从代码示例说明堆和栈

为了更好地说明在Java中堆和栈内存的使用,让我们写一个简单的程序,并决定哪个分配分配到哪个内存——堆或栈:

public class HeapAndStackTest {
    public static void main(String[] args) {
        int x=10;
        int y=20;
        String greet = "Hello";
        Date d = new Date();
        diff(x, y);
    }

    public static int diff(int x1, int x2) {
        return x2-x1;
    }
}

这段代码运行方式如下:

  • 程序启动,JVM将Java运行时环境(JRE)类加载到堆中。
  • 在遇到main() 方法时,会创建一个栈帧。
  • 局部变量xy存储在栈中。
  • 字符串greet分配在堆的StringPool区域中。
  • Date对象分配在堆区,而它的引用d存储在栈中。

Java中的堆和栈

总结

栈和堆是Java程序在代码执行期间使用的两个区域。除了这两个之外,还有其他内存区域,如方法区域、寄存器、本地方法域等等。每种区域在Java应用程序中都有其特定的用途。但是,从程序员的角度来看,栈和堆是JVM必须理解的区域。

参考资料:
https://www.developer.com/java/stack-heap-java-memory/文章来源地址https://www.toymoban.com/news/detail-403427.html

到了这里,关于Java中的堆和栈的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 面试题:堆和栈的区别

    1.管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放由程序员控制,容易产生内存泄漏。 2.空间大小不同。每个进程拥有的栈大小要远远小于堆的大小。理论上进程可申请的堆大小为虚拟内存大小,进程栈的大小64bits的Windows默认1MB,64bits的Lin

    2023年04月09日
    浏览(41)
  • 前端高频面试题 js中堆和栈的区别和浏览器的垃圾回收机制

    栈(stack) :是栈内存的简称,栈是自动分配相对固定大小的内存空间,并由系统自动释放,栈数据结构遵循FILO(first in last out)先进后出的原则,较为经典的就是乒乓球盒结构,先放进去的乒乓球只能最后取出来。 堆(heap) :是堆内存的简称,堆是动态分配内存,内存大小不固

    2024年02月11日
    浏览(44)
  • jvm深入研究文档--java中的堆--详解!--jvm底层探索(1)

    JVM的内存分区包括以下几个部分: 堆区(Heap) - 这是JVM的主要部分,用于存储实例对象和大多数Java对象,如数组和用户定义的类。 方法区(Method Area) - 这是线程私有的,用于存放类对象(加载好的类)。 栈区(Stack) - 这是线程私有的,包括虚拟机栈和本地方法栈。虚拟

    2024年02月07日
    浏览(52)
  • Elastic 栈中的 Kibana安装

    Kibana 是一个开源分析和可视化平台,旨在与 Elasticsearch 协同工作。 你使用 Kibana 搜索,查看和与存储在 Elasticsearch 索引中的数据进行交互。 你可以轻松执行高级数据分析,并在各种图表,表格和地图中可视化你的数据。 官方链接:Kibana:如何在 Linux,MacOS 及 Windows 上安装

    2024年02月11日
    浏览(38)
  • 监控技术栈中的知识点

    一、日志数据和指标数据怎么区别?   日志数据和指标数据是两种常用的监控数据。它们的区别主要体现在以下几个方面: 数据格式 :日志数据通常是文本格式的,而指标数据通常是数字格式的。 数据内容 :日志数据通常记录了系统或应用程序的运行状态,而指标数据通

    2024年02月07日
    浏览(47)
  • git stash弹出栈中的指定内容

    使用 git stash 的相关命令来选择性地弹出特定的 stash 内容,应用到指定的分支上。如果我们使用 git stash 命令已经存储了多个记录时,每个 stash 记录都会有一个唯一的标识符(stash@{0}、stash@{1}…)。通过这些标识符可以应用或弹出特定的 stash 记录。 以下是几个相关的命令:

    2024年01月19日
    浏览(49)
  • 详解数据结构中的堆

    本篇文章主要讲解如何构建一个堆(本文讲的是二叉堆),堆排序以及TOP-K问题。 首先,储存堆我们用到的是数组,我们把它封装为一个结构体 size是数组里面有效数据的个数,capacity是数组的容量大小。 虽然堆在物理结构上是一个数组,但在逻辑结构上我们把它想象做一个

    2024年02月19日
    浏览(36)
  • 堆积如山:探索数据结构中的堆

    前言 欢迎来到小K的数据结构专栏的第十一小节,本节将为大家带来堆的详解并带来堆题目的讲解(✨当然也为大家准备了完整的源码 )~希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🐾 ✨ 在讲堆之前我们先看看满二叉树和完全二叉树~ 一、满二叉树 我们

    2024年02月08日
    浏览(46)
  • 深入理解C++中的堆与栈:内存管理的关键区别与实例解析

      概述: C++中,堆和栈是两种不同的内存分配方式。栈自动分配、释放内存,适用于短生命周期变量;堆需要手动管理,适用于动态分配内存,但需要显式释放以防内存泄漏。通过清晰的示例源代码,演示了它们在变量生命周期、访问方式等方面的区别。 C++中的堆(heap)和

    2024年02月22日
    浏览(68)
  • Java之堆和堆排序

    目录 一.什么是堆 1.基本介绍 2.堆的实现方式 二.最大堆的实现 1.最大堆 2.思路分析 0.基础操作 1.添加+上浮操作 2.删除+下沉操作 3.将数组堆化操作 2.代码实现 三.堆排序 1.什么是堆排序 2.思路分析 3.代码实现 堆是一种数据结构,通常被描述为一棵 完全二叉树 ,其中每个节点

    2023年04月12日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包