# 运行时数据区域

JVM内存共分为虚拟机栈方法区程序计数器本地方法栈五个部分。

线程私有的

  • 程序计数器 Program Counter Register
  • 虚拟机栈 VM Stack
  • 本地方法栈 Native Method Stack

线程共享的

  • 堆 Heap
  • 方法区 Method Area
  • 直接内存(直接内存并不是运行时数据区域的一部分)

# 程序计数器

程序计数器是一块较小的内存空间,是当前线程所执行的字节码的行号指示器。字节码解释器工作时,通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理等都要依赖这个计数器来完成。

每个线程都需要有一个独立的程序计数器,各个线程之间的计数器互不影响,独立存储,所以这块内存区域被称为线程私有的内存。

作用

  • 字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制:顺序执行、选择、循环等。
  • 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而线程被切换回来可以知道上次运行到哪。

程序计数器是唯一一个不会出现OutOfMemoryError的内存区域。生命周期随着线程的创建而创建,随着线程的结束而死亡。

# 虚拟机栈

Java内存可以分为堆内存栈内存,这里的栈指的就是虚拟机栈

虚拟机栈中的局部变量表主要存放了各种数据类型(八种基本数据类型)、对象引用(可能是指向对象起始地址的引用指针)等。

Java虚拟机会出现两种错误:StackOverFlowErrorOutOfMemoryError

Java栈类比数据结构中的栈,保存的主要内容是栈帧,每次的函数调用都有对应的栈帧被压入Java栈,而每次函数的调用结束,都会有一个栈帧被弹出。

# 本地方法栈

本地方法栈与虚拟机栈的区别在于:本地方法栈是为虚拟机使用到的Native方法服务,而虚拟机栈是为执行Java(字节码)服务。「HotSpot」虚拟机中,这两个栈合二为一。

#

堆是Java虚拟机中所管理的内存最大的一块,是所有线程都共享的一块区域。这块区域的目的是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。

Java堆是垃圾收集器管理的主要区域,所以也被称作GC堆。因为垃圾回收器都基本采用分代垃圾回收算法,所以Java堆还可细分为:新生代老年代,目的是为了更好地回收内存,或者更快地分配内存。

# 方法区

方法区也是所有线程都共享的一块区域,用于存储已被虚拟机加载的类信息、常量、静态便令、即时编译后的代码等数据

# 直接内存

直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存被频繁地使用。它避免了在Java堆和Native堆之间来回复制数据。