Java虚拟机学习笔记--第二章 Java内存区域之运行时数据区域(一)

100 阅读3分钟

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,下图是Java虚拟机运行时数据区的分布与功能。

运行时数据区图.jpg

  • 程序计数器
    这块内存比较小,是线程私有的,即每个线程都有自己独立的计数器。 解释器工作是一行一行执行的,就是通过计数器来获取下一行要执行的字节码指令。包括分支、循环、跳转、异常处理、线程切换/恢复,也是通过计数器来确定的。

  • Java虚拟机栈
    也是线程私有的,生命周期与线程相同。每个方法在执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。方法调用到执行,就是对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

    • 局部变量表 存放了编译期可知的八大基本类型(boolean、byte、char、short、int、float、long、double)和reference(指向一个对象地址的引用指针或代表一个对象的句柄)。橙红色箭头是句柄方式访问对象,黄色箭头是直接指针方式访问对象。 局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小
  • 本地方法栈
    本地方法栈与虚拟机栈作用相似,区别在于虚拟机栈为字节码服务,本地方法栈为Native方法(C语言等其它语言内容)服务。

  • Java堆
    是Java虚拟机所管理的最大一块内存,被所有线程共享,虚拟机启动时创建,唯一目的就是存放对象实例,几乎所有对象都在这里分配内存(用“几乎”是因为栈上分配标量替换等优化技术使得不那么绝对)。如果从内存回收的角度看,由于现在收集器基本都是采用分代收集算法,所以还会分为:新生代、老年代。但无论如何划分,存储的都是对象实例,划分与存储内容无关。

  • 方法区
    方法区与Java堆一样,是各个线程共享的内存区域。用于存储已被虚拟机加载的类信息常量静态变量、即时编译器编译后的代码数据。

    • 运行时常量 是方法区的一部分,运行时会把常量池中“符号引用”这部分的内容复制一份存储在运行时常量池中。运行时常量池相对于类信息中的常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有编译期才能产生。关于它的详细介绍,可查看这篇文章《java字符串常量池、class常量池和运行时常量池》

    • 字面量 分文本字符串(String)和final修饰的变量,也就是常量。String是一个不可变类,底层也是使用的final,所以本质也是常量。

    • 符号引用 包括了类/接口的全名、字段名称、字段描述符(字段类型表示的符号)、方法名称、方法描述符(方法可见性public、private、protected)。