《深入理解java虚拟机》第二章:Java内存区域与内存溢出异常-20210716

2.1 概述

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙, 墙外面的人想进去, 墙里面的人却想出来。

2.2 运行时数据区域

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。 这些区域有各自的用途, 以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在, 有些区域则是依赖用户线程的启动和结束而建立和销毁。

 

2-1 Java虚拟机运行时数据区

2.2.1 程序计数器

  程序计数器(Program Counter Register) 是一块较小的内存空间, 可以看作是当前线程所执行的字节码的行号指示器。 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令, 它是程序控制流的指示器, 分支、 循环、 跳转、 异常处理、 线程恢复等基础功能都需要依赖这个计数器来完成。

  由于Java虚拟机的多线程是通过线程轮流切换、 分配处理器执行时间的方式来实现的, 在任何一个确定的时刻, 一个处理器(对于多核处理器来说是一个内核) 都只会执行一条线程中的指令。 因此, 为了线程切换后能恢复到正确的执行位置, 每条线程都需要有一个独立的程序计数器, 各条线程之间计数器互不影响, 独立存储, 我们称这类内存区域为“线程私有”的内存。

  如果线程正在执行的是一个Java方法, 这个计数器记录的是正在执行的虚拟机字节码指令的地址; 如果正在执行的是本地(Native) 方法, 这个计数器值则应为空(Undefined) 。 此内存区域是唯一一个在《Java虚拟机规范》 中没有规定任何OutOfMemoryError情况的区域。

2.2.2 Java虚拟机栈

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

  程序员最关注的、 与对象内存分配关系最密切的区域是“堆”和“栈”两块。程序员最关注的、 与对象内存分配关系最密切的区域是“堆”和“栈”两块。或者更多的情况下只是指虚拟机栈中局部变量表部分。

  局部变量表存放了编译期可知的各种Java虚拟机基本数据类型(boolean、 byte、 char、 short、 int、float、 long、 double) 、 对象引用(reference类型, 它并不等同于对象本身, 可能是一个指向对象起始地址的引用指针, 也可能是指向一个代表对象的句柄或者其他与此对象相关的位置) 和returnAddress 类型(指向了一条字节码指令的地址)。

原文地址:https://www.cnblogs.com/sfnz/p/15019823.html