1. 程序计数器
- 程序计数器是线程私有的;
- 程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器;
- 字节码解释器通过改变程序计数器一次读取指令,从而进行流程控制(分支、循环、异常处理、顺序执行);
- 多线程环境下,程序计数器记录当前线程的执行位置,在线程切换完成后保证程序的正确执行;
2. 虚拟机栈
- Java 虚拟机栈是线程私有的;
- Java 虚拟机栈是由一个个栈帧组成的,每个栈帧都包含局部变量表、操作数栈、动态连接、方法出口信息;
- 局部变量表存放了编译期可知的各种 Java 虚拟机基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型,它并不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与此对象相关的位置)和 returnAddress 类型(指向了一条字节码指令的地址)。
Java 中每一次方法调用都会有一个对应的栈帧被压入栈,每一个方法调用结束(return 或 异常)都会有一个对应的栈帧被弹出。
虚拟机栈描述的是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
3. 堆
- 堆是线程共享的;
- 堆是垃圾回收的主要区域,所有又称为 GC 堆;
- 堆的唯一目的是存放对象实例,几乎所有的对象实例和数组都在堆内存分配空间;
- JDK1.7 字符串常量池被从方法区拿到了堆中;1.8 类变量(静态变量)也被移到了堆内存;
- 根据分代垃圾收集算法,堆可以被细分为新生代和老年代,新生代可以分为 Eden 空间、From Survivor、To Survivor 空间(幸存区,s0,s1);
4. 方法区
- 方法区是线程共享的;
- 方法区主要存储已被虚拟机加载的类信息、常量(运行时常量池)、静态变量、即时编译器编译后的代码;
- 方法区是是一种概念,不同虚拟机对该空间的实现不同。永久代就是 HotSpot 虚拟机对虚拟机规范中方法区的一种实现方式;1.8 时方法区(HotSpot的永久代)被元空间(MetaSpace)取代,元空间使用的时直接内存;
图片来源:JavaGuide