写点什么

《深入理解 Java 虚拟机》读后笔记 - 运行时数据区域

  • 2022 年 5 月 12 日
  • 本文字数:1605 字

    阅读完需:约 5 分钟

Java 虚拟机栈与程序计数器一样,也是线程私有的,它的生命周期与线程相同


  • 虚拟机栈描述的是 Java 方法执行的线程内存模型:每个方法被执行的时候 Java 虚拟机都会同步创建一个栈帧 (Stack Frame)用于存储局部变量表操作数栈动态连接方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

  • 局部变量表存放了编译期可知的各种 Java 虚拟机基本数据类型(booleanbytecharshortintfloatlongdouble)、对象引用(reference 类型)和 returnAddress 类型(指向了一条字节码指令的地址)。

  • 这些数据类型在局部变量表中的存储空间以局部变量槽(Slot)来表示,其中 64 位长度的longdouble类型的数据会占用两个变量槽,其余的数据类型只占用一个。

  • 局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。这里说的“大小”是指变量槽的数量。

  • 在《Java 虚拟机规范》中,对这个内存区域规定了两类异常状况:


  1. 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常

  2. 如果 Java 虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常。


[](()3.本地方法栈




本地方法栈与虚拟机栈所发挥的作用是非常相似的,其区别只是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的本地(Native) 方法服务。


与虚拟机栈一样,本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出StackOverflowErrorOutOfMemoryError异常。


[](()4.Java 堆




Java 堆对于 Java 应用程序来说**,是虚拟机所管理的内存中最大的一块**。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建**。此内存区域的唯一目的就是存放对象实例**,Java 世界里几乎所有的对象实例都在这里分配内存。


  • Java 堆是垃圾收集器管理的内存区域,因此一些资料中它也被称作 GC 堆

  • 如果从分配内存的角度看,所有线程共享的 Java 堆中可以划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB),以提升对象分配时的效率

  • Java 堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的,这点就像我们用磁盘空间去存储文件一样,并不要求每个文件都连续存放。但对于大对象(典型的如数组对象),多数虚拟机实现出于实现简单、存储高效的考虑,很可能会要求连续的内存空间。

  • Java 堆既可以被实现成固定大小的,也可以是可扩展的,不过当前主流的 Java 虚拟机都是按照可扩展来实现的(通过参数-Xmx-Xms设定)。

  • 如果在 Java 堆中没有内存完成实例分配,并且堆也无法再扩展时,Java 虚拟机将会抛出OutOfMemoryError异常。


[](()5.方法区




方法区与 Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 存等数据


方法区只是一个抽象概念,其具体实现是通过以下 2 种方式:


  • JDK7 之前:永久代,使用的堆内存

  • JDK8 之后:元空间,使用的本地内存


具体过程变更过程:


  1. JDK 6的时候 HotSpot 开发团队就有放弃永久代,逐步改为采用本地内存来实现方法区的计划了。

  2. 到了JDK 7的 HotSpot,已经把原本放在永久代的字符串常量池、静态变量等移出。

  3. 而到了JDK 8,终于完全废弃了永久代的概念,改用在本地内存中实现的元空间来代替,把 JDK 7 中永久代还剩余的内容(主要是类型信息)全部移到元空间中。



根据《Java 虚拟机规范》的规定,如果方法区无法满足新的内存分配需求时,将抛出OutOfMemoryError异常。


  • 1.8 以前会导致永久代内存溢出java.lang.OutOfMemoryError: PermGen space

  • 1.8 以后会导致元空间内存溢出java.lang.OutOfMemoryError: Metaspace


[](()6.运行时常量池




运行时常量池是方法区的一部分

用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
《深入理解Java虚拟机》读后笔记-运行时数据区域_Java_爱好编程进阶_InfoQ写作社区