JVM学习记录——运行时数据区

JVM规范中规定,运行时数据区(Runtime Data Area)通常包含

  • 程序计数器(Program Counter Register)
  • Java栈(VM Stack)
  • 本地方法栈(Native Method Stack)
  • 方法区(Method Area)
  • 堆(Heap)


从图中可以看出,只有方法区和堆是线程共享的,其他都是线程私有的。通常地,一个Java程序是一个进程,也是Tomcat(或其他服务容器)实例。进程每创建一个线程都有独立的 程序计数器、Java栈、本地方法栈

堆(Heap)

堆是管理内存中最大的一块,负责存储对象实例和数组,在JVM启动的时候创建的,即一个Java进程对应一个堆。里面的对象是所有线程共享的,所以在多线程操作同一个对象时候要注意数据安全性问题。对象会被自动管理,也就是垃圾回收时,回收的就是这块的内存。
该区域的大小通过JVM参数 -Xmx、-Xms控制。

虚拟机栈(Virtual Machine Stack)

在线程被创建的时候,会同时创建一个该线程私有的栈,即一个线程对应一个栈,生命周期也是相同的。栈用于Java执行时候的内存模型,每执行一个方法都会同时创建栈帧(Stack Frame),每个栈帧里面存储 存储局部变量表、操作数栈、动态链接、方法出口等信息。线程执行,相同于入一个栈帧,操作里面的变量等数据完成这个方法,然后出栈,切换下一个方法。
栈大小可通过 -Xss设置。

本地方法栈(Native Method Stack)

与虚拟机栈基本相同,只是本地方法栈服务的对象是本地的服务,如一些JVM自身的方法、系统底层的调用等。

方法区(Method Area or Permanent Generation)

用于存储一些静态信息。例如类信息,常量,静态变量等,即编译后一些代码数据。方法区的数据也是线程共享的。
一些地方也会说到常量池,也是在其中。

程序计数器(Program Counter Register)

线程私有,用于保存执行指令的地址,有别于实际的PC寄存器。实际PC寄存器是基于CPU使用的,JVM在执行程序的时候,CPU会变换的执行不同的线程,所以JVM程序在执行不同线程的时候,需要保存各个线程的执行指令的地址,以便恢复执行。

听说你想请我喝下午茶?~