Java 堆空间与堆栈 - Java 中的内存分配

2023-11-15

不久前我写了几篇关于Java 垃圾收集 and Java 是按值传递。之后我收到了很多电子邮件来解释Java堆空间, Java堆栈内存, Java中的内存分配它们之间有什么区别?您会在 Java、Java EE 书籍和教程中看到很多对堆和堆栈内存的参考,但几乎没有从程序的角度完整解释什么是堆和堆栈内存。

Java堆空间

Java 运行时使用 Java 堆空间为对象和 JRE 类分配内存。每当我们创建一个对象时,它总是在堆空间中创建。垃圾收集在堆内存上运行,以释放没有任何引用的对象使用的内存。在堆空间中创建的任何对象都具有全局访问权限,并且可以从应用程序的任何位置引用。

Java堆栈内存

Java 堆栈内存用于执行线程。它们包含特定于方法的短暂值以及对堆中从该方法引用的其他对象的引用。堆栈内存始终按 LIFO(后进先出)顺序引用。每当调用一个方法时,都会在堆栈内存中创建一个新块,以便该方法保存本地原始值并引用该方法中的其他对象。一旦该方法结束,该块就会变得未使用并可用于下一个方法。与堆内存相比,堆栈内存大小非常小。

Java程序中的堆和栈内存

让我们通过一个简单的程序来了解堆和堆栈内存的使用情况。

package com.journaldev.test;

public class Memory {

	public static void main(String[] args) { // Line 1
		int i=1; // Line 2
		Object obj = new Object(); // Line 3
		Memory mem = new Memory(); // Line 4
		mem.foo(obj); // Line 5
	} // Line 9

	private void foo(Object param) { // Line 6
		String str = param.toString(); //// Line 7
		System.out.println(str);
	} // Line 8

}

The below image shows the Stack and Heap memory with reference to the above program and how they are being used to store primitive, Objects and reference variables. java memory management, java heap space, heap vs stack, java heap, stack vs heap Let’s go through the steps of the execution of the program.

  • 一旦我们运行程序,它就会将所有运行时类加载到堆空间中。当在第 1 行找到 main() 方法时,Java 运行时会创建供 main() 方法线程使用的堆栈内存。
  • 我们在第 2 行创建原始局部变量,因此它被创建并存储在 main() 方法的堆栈内存中。
  • 由于我们在第三行创建一个对象,因此它是在堆内存中创建的,而堆栈内存包含它的引用。当我们在第 4 行创建 Memory 对象时,会发生类似的过程。
  • 现在,当我们在第 5 行调用 foo() 方法时,会在堆栈顶部创建一个块以供 foo() 方法使用。由于 Java 是按值传递的,因此在第 6 行的 foo() 堆栈块中创建了对 Object 的新引用。
  • 第 7 行创建了一个字符串,它进入字符串池在堆空间中,并在 foo() 堆栈空间中为其创建一个引用。
  • foo()方法在第8行终止,此时栈中为foo()分配的内存块变得空闲。
  • 在第 9 行,main() 方法终止,为 main() 方法创建的堆栈内存被销毁。此外,程序在这一行结束,因此 Java 运行时释放所有内存并结束程序的执行。

Java堆空间和堆栈内存的区别

根据上面的解释,我们可以很容易地得出堆内存和栈内存的以下区别。

  1. 堆内存由应用程序的所有部分使用,而堆栈内存仅由一个执行线程使用。
  2. 每当创建一个对象时,它总是存储在堆空间中,并且堆栈内存包含对其的引用。堆栈内存仅包含局部原始变量和堆空间中对象的引用变量。
  3. 存储在堆中的对象可以全局访问,而堆栈内存不能被其他线程访问。
  4. 堆栈中的内存管理以 LIFO 方式完成,而堆内存中的内存管理更复杂,因为它是全局使用的。堆内存分为Young-Generation、Old-Generation等,更多详细信息请参见Java 垃圾收集.
  5. 堆栈内存是短暂的,而堆内存从应用程序执行开始到结束都存在。
  6. 我们可以用-Xms and -XmxJVM选项定义堆内存的启动大小和最大大小。我们可以用-Xss定义堆栈内存大小。
  7. 当堆栈内存已满时,Java运行时会抛出异常java.lang.StackOverFlowError而如果堆内存已满,则会抛出java.lang.OutOfMemoryError: Java Heap Space error.
  8. 与堆内存相比,堆栈内存大小非常小。由于内存分配 (LIFO) 简单,因此与堆内存相比,堆栈内存非常快。

这就是全部Java 堆空间与堆栈内存就java应用程序而言,我希望它能消除您对执行任何java程序时的内存分配的疑虑。

参考:https://en.wikipedia.org/wiki/Java_memory_model.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 堆空间与堆栈 - Java 中的内存分配 的相关文章

  • 读取文件并获取 key=value 而不使用 java.util.Properties

    我正在构建一个 RMI 游戏 客户端将加载一个包含一些键和值的文件 这些键和值将用于多个不同的对象 它是一个保存游戏文件 但我不能为此使用 java util Properties 它符合规范 我必须读取整个文件并忽略注释行和与某些类不相关
  • 如何用Java写入OS系统日志?

    Mac OS 有一个名为 Console 的应用程序 其中包含记录的消息 错误和故障 我相信 Windows 中的等效项是事件查看器 我想 Linux 上也有一个 但我不知道它是什么 也不知道它在哪里 是否可以像这样从 Java 输出获取消
  • Java - 从配置文件加密/解密用户名和密码

    我们正忙于为客户开发 Java Web 服务 有两种可能的选择 将加密的用户名 密码存储在Web服务客户端上 从配置中读取 文件在客户端 解密并发送 将加密的用户名 密码存储在 Web 服务器上 从配置中读取 Web 服务器上的文件 解密并
  • 如何降低圈复杂度?

    我正在开发一个将 RequestDTO 发送到 Web 服务的类 我需要在发送请求之前验证该请求 请求可以从 3 个不同的地方发送 并且每个 请求类型 有不同的验证规则 例如请求1必须有姓名和电话号码 请求2必须有地址等 我有一个 DTO
  • 如何使用 Java 创建多个模式连接?

    我必须使用两个数据库 DB2 Oracle 我在 DB2 数据库中有一个名为NAVID 我想使用 Java 为 Oracle 中的所有表创建相同的架构 public class automateExport static String va
  • 如何防止在 CXF Web 服务客户端中生成 JAXBElement

    我正在尝试使用 CXF 创建一个 Web 服务客户端来使用 WCF Web 服务 当我使用 wsdl2java 时 它生成具有 JAXBElement 类型而不是 String 的对象 我读到有关使用 jaxb bindings xml 文
  • 在 Tomcat 上部署 Java Web 项目,无需 WAR 或 EAR

    我有一个 Java Web 项目 Struts Spring 在我的本地主机上完美运行 我必须将其部署在我的网站上 但虚拟主机提供的 Tomcat Manager 界面显示 由于安全原因 它无法上传 WAR 文件 当联系技术支持时 我被告知
  • H264 字节流到图像文件

    第一次来这里所以要温柔 我已经在给定的 H 264 字节流上工作了几个星期 一般注意事项 字节流不是来自文件 它是从外部源实时提供给我的 字节流使用 Android 的媒体编解码器进行编码 当将流写入扩展名为 H264的文件时 VLC能够正
  • 在哈希图中存储字符和二进制数

    我正在尝试存储字母到二进制数的映射 这是我的映射 h 001 i 010 k 011 l 100 r 101 s 110 t 111 为此 我创建了一个哈希映射并存储了键值对 我现在想显示给定句子的相应二进制值 这是我的代码 package
  • 使用 JAXB 编组 LocalDate

    我正在构建一系列链接类 我希望能够将其实例编组到 XML 以便我可以将它们保存到文件中并稍后再次读取它们 目前我使用以下代码作为测试用例 import javax xml bind annotation import javax xml b
  • 如果按下 Esc 则中断循环

    我用 JAVA 语言编写了一个程序 它使用 Scanner 类接受来自控制台的输入 现在我想将此功能添加到我的代码中 以便在用户按下 Esc 按钮时存在循环 while 到目前为止 我认为键盘类可以帮助我 但它就像扫描仪一样 我尝试使用事件
  • JAX-WS:有状态 WS 在独立进程中失败

    我在 Tomcat 上部署了一个有状态的 Web 服务 它由工厂服务和主要 API 服务组成 并且工作得很好 工厂服务将 W3CEndpointReference 返回到主 API 实例 客户端使用会话 现在 我尝试将相同的服务作为独立应用
  • 动画图像视图

    目前我正在开发一款游戏 这是我的游戏的详细信息 用户应选择正确的图像对象 我希望图像从左到右加速 当他们到达终点时 他们应该再次出现在活动中 这是我正在处理的屏幕截图 我有 5 个图像视图 它们应该会加速 您有此类动画的示例代码吗 非常感谢
  • 通过 JNI 从 Applet 调用 DLL

    我有一个 概念验证 的作品 它跨越了一些不熟悉的领域 我的任务是将 EFTPOS 机器连接到在内联网浏览器中作为小程序运行的应用程序 我暂时忽略了 EFTPOS dll 并用我选择的语言 Delphi 创建了一个简单的 JNI 修饰的 DL
  • 中间件 API 的最佳实践是什么? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我们正在开发一个中间件 SDK 采用 C 和 Java 语言 供游戏开发人员 动画软件开发人员 阿凡达开
  • 在多模块项目中访问绑定适配器

    我有一个多模块项目 其中应用程序模块包含我的绑定适配器 而我的功能模块取决于我的应用程序模块 因为它是动态功能模块 应用程序 包含绑定适配器 gt 动态功能模块 存在布局的地方 我在所有模块中启用了数据绑定和 kapt 我无法成功构建应用程
  • 膨胀类片段 InflateException 二进制 XML 文件时出错

    我正在使用 Material Design 和 NavigationDrawer 布局等设计我的第一个应用程序 但我遇到了一个问题 该应用程序非常简单 它只显示文本 并且基于 Android Studio 中提供的模板 尝试启动我的应用程序
  • Java 8根据Map属性过滤Map对象列表以删除一些重复项

    Have a List
  • 如何将任务添加到 gradle 中的主要“构建”任务

    当我尝试使用以下代码将任务添加到主构建任务时 rootProject tasks getByName build dependsOn mytask 当我跑步时它抱怨gradle w build输出 Where Build file line
  • java中的回调是什么[重复]

    这个问题在这里已经有答案了 可能的重复 什么是回调函数 https stackoverflow com questions 824234 what is a callback function 我已经阅读了回调的维基百科定义 但我仍然没有明

随机推荐

  • 如何在 CentOS 7 上部署 Mattermost

    Mattermost 是一个开源即时通讯平台 是一个自托管的 Slack 替代品 它是用 Golang 和 React 编写的 可以使用 MySQL 或 PostgreSQL 作为数据库后端 Mattermost 将您的所有团队沟通集中到一
  • 如何在 CentOS 7 上安装 Plex 媒体服务器

    Plex 是一款流媒体服务器 可将您所有的视频 音乐和照片收藏集中在一起 并随时随地将它们流式传输到您的设备 在本教程中 我们将向您展示如何安装和配置Plex 媒体服务器在 CentOS 7 上 先决条件 在继续本教程之前 请确保您以以下身
  • Linux 中的 df 命令(检查磁盘空间)

    我的硬盘还剩多少空间 是否有足够的可用磁盘空间来下载大文件或安装新应用程序 在 Linux 和 Unix 操作系统上 您可以使用df命令获取有关系统磁盘空间使用情况的详细报告 使用 df 命令 的一般语法为df命令如下 df OPTIONS
  • 如何在 CentOS 8 上安装 Node.js 和 npm

    Node js 是一个基于 Chrome JavaScript 构建的跨平台 JavaScript 运行时环境 旨在在服务器端执行 JavaScript 代码 使用 Node js 您可以构建可扩展的网络应用程序 npm 是 Node Pa
  • 如何在 Debian 9 上安装 Webmin

    Webmin是一个用于管理 Linux 服务器的开源 Web 控制面板 使用 Webmin 您可以管理系统用户 组 磁盘配额以及配置最流行的服务 包括 Web ssh ftp 电子邮件和数据库服务器 本教程介绍如何在 Debian Linu
  • 如何在 Debian 11 上为专用连接设置 Squid 代理

    介绍 代理服务器是一种服务器应用程序 充当最终用户和互联网资源之间的网关 通过代理服务器 最终用户能够出于多种目的控制和监视其 Web 流量 包括隐私 安全和缓存 例如 您可以使用代理服务器从与您自己的 IP 地址不同的 IP 地址发出 W
  • 如何在 Ubuntu 16.04 上安装 MySQL

    介绍 MySQL是一个开源数据库管理系统 通常作为流行的一部分安装LAMP Linux Apache MySQL PHP Python Perl 堆栈 它使用关系数据库和 SQL 结构化查询语言 来管理其数据 简短版本的安装很简单 更新您的
  • Java IO 教程

    Java提供了几个类java io用于处理文本 流数据和文件系统的包 我最近提供了几个有关 Java 文件和 Java IO 的示例 这篇文章是所有 Java IO 文章的索引 Java IO 如何在 Java 中创建新文件在这篇文章中 您
  • Java Stream Collect() 方法示例

    Java Streamcollect 对流的元素执行可变归约操作 这是终端操作 什么是可变约简操作 可变归约操作处理流元素 然后将其累积到可变结果容器中 处理元素后 组合函数将合并所有结果容器以创建结果 Java Stream Collec
  • 快速初始化()

    在本 Swift 教程中 我们将讨论一个重要的概念 即 Swift init 或 Swift 初始化 初始化是当我们创建某种类型的实例时发生的事情 快速初始化 初始化是准备类 结构或枚举的实例以供使用的过程 此过程涉及为该实例上的每个存储属
  • 如何在 Debian Wheezy 上使用 Postfix 安装和配置 DKIM

    介绍 对于大多数邮件服务器管理员来说 被错误地标记为垃圾邮件发送者所带来的挫败感并不奇怪 通过排除服务器受损的可能性 错误标记通常是由以下原因之一引起的 该服务器是一个开放的邮件中继 发件人或服务器的 IP 地址已列入黑名单 服务器没有完全
  • Linux/Unix 中的 AWK 命令

    AWK 适用于模式搜索和处理 该脚本运行以搜索一个或多个文件以识别匹配模式以及所述模式是否执行特定任务 在本指南中 我们将了解 AWK Linux 命令并了解它的功能 AWK 可以执行哪些操作 逐行扫描文件 将每个输入行拆分为字段 将输入行
  • 如何在 Python 中将字符串转换为日期时间或时间对象

    介绍 蟒蛇datetime and time模块均包括strptime 将字符串转换为对象的类方法 在本文中 您将使用strptime 将字符串转换为datetime and struct time 对象 将字符串转换为datetime对象
  • 如何在 Ubuntu 18.04 上使用 Python 3 设置 Jupyter Notebook

    介绍 Jupyter笔记本是一个开源 Web 应用程序 可让您创建和共享交互式代码 可视化等 该工具可与多种编程语言一起使用 包括 Python Julia R Haskell 和 Ruby 它通常用于处理数据 统计建模和机器学习 本教程将
  • 了解 Vue.js 生命周期挂钩

    介绍 生命周期挂钩是了解您正在使用的库如何在幕后工作的窗口 生命周期钩子允许您知道组件何时被创建 添加到 DOM 更新或销毁 本文将向您介绍 Vue js 中的创建 安装 更新和销毁钩子 先决条件 要完成本教程 您需要 熟悉 Vue js
  • Java 单例类中的线程安全

    Singleton 是最广泛使用的创建型设计模式之一 用于限制应用程序创建的对象 如果是在多线程环境中使用 那么单例类的线程安全性就非常重要 在现实应用程序中 数据库连接或企业信息系统 EIS 等资源是有限的 应明智地使用以避免任何资源紧缩
  • Fail2Ban 如何保护 Linux 服务器上的服务

    介绍 SSH 是连接云服务器的事实上的方法 它耐用且可扩展 随着新的加密标准的开发 它们可用于生成新的 SSH 密钥 确保核心协议保持安全 然而 没有任何协议或软件堆栈是完全万无一失的 SSH 在互联网上如此广泛的部署意味着它代表了一种非常
  • 如何在运行 Ubuntu 的 VPS 上安装和使用 Composer

    Status 已弃用 本文介绍不再受支持的 Ubuntu 版本 如果您当前运行的服务器运行 Ubuntu 12 04 我们强烈建议您升级或迁移到受支持的 Ubuntu 版本 升级到Ubuntu 14 04 从 Ubuntu 14 04 升级
  • 如何在 Rocky Linux 9 上安装 Node.js

    介绍 Node js是用于服务器端编程的 JavaScript 运行时 它允许开发人员使用 JavaScript 创建可扩展的后端功能 这是许多人在基于浏览器的 Web 开发中已经熟悉的语言 在本指南中 您将了解在 Rocky Linux
  • Java 堆空间与堆栈 - Java 中的内存分配

    不久前我写了几篇关于Java 垃圾收集 and Java 是按值传递 之后我收到了很多电子邮件来解释Java堆空间 Java堆栈内存 Java中的内存分配它们之间有什么区别 您会在 Java Java EE 书籍和教程中看到很多对堆和堆栈内