JVM中的堆和栈到底存储了什么

2023-05-16

JVM数据区

先上一张Java虚拟机运行时数据区中堆、栈以及方法区存储数据的概要图,如下所示:

 

然后我们来具体解析一下堆和栈

堆是存储时的单位,对于绝大多数应用来说,这块区域是 JVM 所管理的内存中最大的一块。线程共享,主要是存放对象实例和数组。

栈是运行时的单位,Java 虚拟机栈,线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。

局部变量表:存放了编译期可知的各种基本类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型)和 returnAddress 类型(指向了一条字节码指令的地址)

堆和栈的对比

一、栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;堆解决的是数据存储的问题,即数据怎么放、放在哪儿。

二、栈因为是运行单位,因此里面存储的信息都是跟当前线程相关的信息。包括:局部变量、程序运行状态、方法返回值等等;而堆只负责存储对象信息。

三、在方法中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。堆内存用于存放由new创建的对象和数组。

四、在Java中一个线程就会相应有一个线程栈与之对应,这点保证了程序的并发运行。

而堆则是所有线程共享的,也可以理解为多个线程访问同一个对象,比如多线程去读写同一个对象的值

五、栈内存溢出包括StackOverflowError和OutOfMemoryError。StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度。OutOfMemoryError:如果虚拟机栈可以动态扩展,而扩展时无法申请到足够的内存;堆内存溢出是OutOfMemoryError。如果堆中没有内存完成实例分配,并且堆也无法再扩展时,抛出OutOfMemoryError异常。

代码分析

最后,借助网上看到的一个例子帮助对栈内存,堆内存的存储进行理解:

 

 

对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:

1. main

方法开始执行:int date = 9;

date

局部变量,基础类型,引用和值都存在栈中。

2. Test test = new Test();

test

为对象引用,存在栈中,对象(new Test())存在堆中。

3. test.change(date);

调用change(int i)方法,i为局部变量,引用和值存在栈中。当方法change执行完成后,i就会从栈中消失。

4. BirthDate d1= new BirthDate(7,7,1970);

调用BIrthDate类的构造函数生成对象。

d1为对象引用,存在栈中;

对象(new BirthDate())存在堆中;

其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中;

day,month,year为BirthDate对象的的成员变量,它们存储在堆中存储的new BirthDate()对象里面;

当BirthDate构造方法执行完之后,d,m,y将从栈中消失。

5.main方法执行完之后。

date变量,test,d1引用将从栈中消失;

new Test(),new BirthDate()将等待垃圾回收器进行回收。

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

JVM中的堆和栈到底存储了什么 的相关文章

  • 在消费者线程中使用 JNI 的生产者-消费者程序中无法捕获 SIGINT 信号

    我正在为生产者消费者问题编写一个程序 生产者生产数据并将数据推送到boost spsc queue消费者处理它 在消费者线程中 我正在使用JNI从我用 c 编写的代码中调用一些 java 函数 I am initializing and c
  • Android Studio 构建 gradle OutOfMemoryError

    我是安卓新手 我在 Android studio 中导入 Github 项目 但我看到这个问题 Error java lang OutOfMemoryError Java heap space 错误 java lang OutOfMemor
  • Java中静态字段的确切含义是什么?

    我想在同一类对象的各个实例之间共享一个对象 从概念上讲 当我的程序运行时 A 类的所有对象都访问 B 类的同一个对象 我见过那个static是系统范围的 并且不鼓励使用它 这是否意味着如果我有另一个程序在实例化 A 类对象的同一个 JVM
  • 为什么要实现finalize()?

    我已经阅读了很多 Java 新手问题finalize 令人困惑的是 没有人真正明确表示 Finalize 是一种不可靠的清理资源的方法 我看到有人评论说他们用它来清理连接 这真的很可怕 因为接近保证连接关闭的唯一方法是最后实现 try ca
  • 内存中的方法表示是什么?

    在思考一下 Java C 编程时 我想知道属于对象的方法如何在内存中表示 以及这一事实如何涉及多线程 是为内存中的每个对象单独实例化一个方法还是执行 同一类型的所有对象共享该方法的一个实例 如果是后者 执行线程如何知道哪个对象是 要使用的属
  • 显示JVM中当前运行的所有线程组和线程

    所以我的任务是显示所有线程组以及当前在 JVM 中运行的属于这些组的所有线程 输出时应首先显示线程组 然后在下面显示该组中的所有线程 这是针对所有线程组完成的 目前 我的代码将仅显示每个线程组 然后显示每个线程 但我不确定如何达到我所描述的
  • Lambda 性能改进,Java 8 与 11

    我对 lambda 与方法参考运行了一些 JMH 测试 看起来类似于 IntStream reduce Integer max vs IntSream reduce i1 i2 gt Integer max i1 i2 我注意到 在 Jav
  • 当 Java 中的集合超出容量时会发生什么?

    我有一个服务 它将所有对其进行的调用暂存在内存中 因为我们不想丢失数据 同时我们需要该服务因任何外部依赖项 例如数据库 而失败 然后 这些分阶段的调用会在后台例行接收和处理 如果出于任何原因 如果调用太多并且内存不足 我们就需要警惕 所以
  • 最近有关于 JVM 的书吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何减少Scala中创建的对象数量?

    我正在 Scala 中编写一个计算机图形应用程序 它使用 RGB 类返回图像中某个点的颜色 正如你可以想象的 返回颜色 RGB 对象的函数被调用了很多次 class RGB val red Int val green Int val blu
  • Java 接口合成方法生成,同时缩小返回类型

    我有 2 个接口和 2 个返回类型 interface interfaceA Publisher
  • JVM 是否会内联对象的实例变量和方法?

    假设我有一个非常紧密的内部循环 每次迭代都会访问和改变一个簿记对象 该对象存储有关算法的一些简单数据 并具有用于操作它的简单逻辑 簿记对象是私有的和最终的 并且它的所有方法都是私有的 最终的和 inline 下面是一个示例 Scala 语法
  • Scala 对大数的阶乘有时会崩溃,有时不会

    以下程序经过编译和测试 有时返回结果 有时充满屏幕 java lang StackOverflowError at scala BigInt apply BigInt scala 47 at scala BigInt equals BigI
  • Java GuardedString - 用于加密的随机密钥是否存储在 Java 堆内存中?如果不是,那么密钥保存在哪里?

    Oracle 的 org identityconnectors common security GuardedString 要转换为 GuardedString 的原始数据需要由 EncryptorImpl class 随机生成的加密密钥
  • 监控 Java 应用程序上的锁争用

    我正在尝试创建一个小基准 在 Groovy 中 以显示几个同步方法上的高线程争用 当监控自愿上下文切换时 应该会出现高争用 在 Linux 中 这可以通过 pidstat 来实现 程序如下 class Res private int n s
  • 强制jvm返回本机内存[重复]

    这个问题在这里已经有答案了 我时不时地运行需要大量内存的 eclipse 任务 因此 当任务运行时 jvm 会消耗大约 2 3GB 的 RAM 这是可以的 但是一旦 jvm 占用了该内存 它就不会释放它 并且我遇到了一种情况 堆中已用内存约
  • 如何在Java中计算对象的数字年龄[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道Java中对象的年龄 当我们使用new关键字时 Java中用户定义的对象被创建 但是什么时候它会被销毁 是跨越JVM的perm
  • OQL 包中的所有实例

    是否有可能在OQL检索属于一个包的所有对象 或者我可以查询wildcards 正如 haridsv 建议我尝试过的 SELECT from com example and SELECT a from com example but in V
  • 如何使用 Java 引用释放 Java Unsafe 内存?

    Java Unsafe 类允许您按如下方式为对象分配内存 但是使用此方法在完成后如何释放分配的内存 因为它不提供内存地址 Field f Unsafe class getDeclaredField theUnsafe Internal re
  • UseCompressedOops JVM 标志有什么作用以及何时应该使用它?

    HotSpot JVM 标志是什么 XX UseCompressedOops我应该做什么以及什么时候使用它 在 64 位 Java 实例上使用它 与不使用它 时 我会看到什么样的性能和内存使用差异 去年大多数 HotSpot JVM 都默认

随机推荐