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

以下内容为周志明《深入理解Java虚拟机》中的内容摘要。写本文来作为学习笔记。

Java 虚拟机在运行时会将管理的内存划分成若干个区域,这些区域各有各的用途,以及各自的创建和销毁的时间。

有些随着虚拟机进程的启动而存在,有些依赖用户线程的启动和结束而建立和销毁。

Java虚拟机所管理的运行时数据区域如下图。
《Java虚拟机:运行时数据区域-《深入理解Java虚拟机》笔记》

运行时数据区分为 线程共享的 与 线程私有的
线程共享的区域包括:方法区,堆。
线程私有的区域包括:虚拟机栈,本地方法栈,程序计数器。

这些区域都需要在运行时分配空间,除了程序计数器,当其他区域因为内存不足无法分配空间时,会抛出OutOfMemory异常。

  1. 程序计数器:
    线程私有,可以看做当前线程所执行字节码的行号指示器。每一个线程都有一个独立的程序计数器。
    分支,循环,跳转,异常处理,线程恢复等功能都依赖它完成。
    如果线程执行的是Java方法, 则记录的是正在执行的虚拟机字节码指令地址,如果线程执行的Native方法,
    则计数器值为空。

  2. 虚拟机栈:
    生命周期与线程相同,每个方法执行时会建立一个栈帧(运行时的一种数据结构),每个栈帧中存放了方法
    的局部变量表,操作数栈,动态链接,方法出口等信息。
    每一个方法调用到执行完毕,都对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

    如果线程请求的栈深度虚拟机所允许的深度,将抛出StackOverflowError,如果虚拟机栈可以动态扩展,
    扩展时无法申请足够的内存,将抛出OutOfMemoryError.
    
  3. 本地方法栈:
    与虚拟机栈作用类似,不过是为Native方法服务的。同样会出现StackOverflowError以及OutOfMemoryError

  4. Java堆:
    唯一目的就是存放对象实例。虚拟机规范规定所有 对象 和 数组 都在堆上分配,不过后来的技术发展让这个
    规定不那么绝对了。
    这块区域是垃圾收集器管理的主要区域。也被称为GC堆。如果收集器采取分代收集算法,堆可以细分为Eden
    空间,From Survivor空间,To Survivor空间。

  5. 方法区:
    用于保存已加载的类信息,常量,静态变量,即时编译后的代码等信息。可以这样理解,是保存Class
    相关的信息的。
    根据Java虚拟机规范,它是堆的一个逻辑部分,但有一个别名叫做Non-Heap 非堆。
    当方法区无法满足内存分配时,会抛出OutOfMemoryError。

  6. 运行时常量池:
    是方法区的一部分,用于存放编译期生成的各种字面量符号引用。将在类加载后保存进运行时常量
    池。运行时常量池在运行期也可能将新的常量放入池中:例如String的intern()方法。

  7. 直接内存:
    不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。但这部分内存频繁使用,也
    可能导致OutOfMemoryError。
    NIO下的类通过基于通道(Channel)与缓冲区(Buffer)的I/O方式,可以直接使用本地方法分配堆外内存。

    原文作者:java虚拟机
    原文地址: https://blog.csdn.net/thezprogram/article/details/83040911
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞