JVM运行时数据区

概述:我个人的理解将JVM运行时数据区分成两块来讲

1. 线程不共享区域
虚拟机栈、 本地方法栈、程序计数器
2. 线程共享区域
堆、方法区(元空间)

先来说线程不共享的区域

虚拟机栈:Java线程执行方法的内存模型,一个线程对应一个栈,每个方法在执行的同时都会创建一个栈帧(用于存储局部变量 表,操作数栈,动态链接,方法出口等信息)不存在垃圾回收问题,只要线程一结束该栈就释放,生命周期和线程一 致
每个栈帧组成如下:

  1. 局部变量表:存储方法中产生的临时变量
  2. 操作数栈:用于操作从局部变量表中复制过来的变量,有压栈和出栈和计算的操作
  3. 动态链接:在程序运行期间,由符号引用(class的引用地址)转化为直接引用(具体的实例对象)ps:静态链接是指程序编译期间,由符号引用转化为直接引用
  4. 返回地址:当一个方法被执行后,在方法退出之后,都需要返回到方法被调用的位置,程序才能继续执行,退出时的执行的操作:恢复上层方法的局部变量表和操作数栈,如果有返回值,则把它压入调用者栈帧的操作数栈中。

程序计数器:就是一个指针,指向方法区中的方法字节码(用来存储指向吓一跳指令的地址,也即将要执行的指令代码),由执行 引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。
本地方法栈:和栈作用很相似,区别不过是Java栈为JVM执行Java方法服务,而本地方法栈为JVM执行native方法服务。登记native 方法,在Execution Engine执行时加载本地方法库。

线程共享的区域

方法区(Method Area)

类的所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在这里定义。简单来说,所有定义的方法的 信息都保存在该区域,静态变量+常量+类信息(构造方法/接口定义)+运行时常量池都存在方法区中,虽然Java虚拟 机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是为了和Java的 堆区分开(jdk1.8以前hotspot虚拟机叫永久代、持久代,jdk1.8时叫元空间)

堆(Heap)

虚拟机启动时自动分配创建,用于存放对象的实例,几乎所有对象都在堆上分配内存,当对象无法在该空间申请到内 存是将抛出OutOfMemoryError异常。同时也是垃圾收集器管理的主要区域。


堆.png

新生代(Young Generation)
类出生、成长、消亡的区域,一个类在这里产生,应用,后被垃圾回收器收集,结束生命。
新生代分为两部分:伊甸区(Eden space)和幸存者区(Survivor space),所有的类都是在伊甸区被new出来的。 幸存区又分为From和To区。当Eden区的空间用完是,程序又需要创建对象,JVM的垃圾回收器将Eden区进行垃圾回 收(Minor GC),将Eden区中的不再被其它对象应用的对象进行销毁。然后将Eden区中剩余的对象移到From Survivor区。若From Survivor区也满了,再对该区进行垃圾回收,然后移动到To Survivor区。
Form 和To 相互转换15次时会转移到老年代。为什么是15次呢,因为jdk有个文件markOop.hpp中64位配置项的age是4 表示4个bit位,转成十进制是0~15,所以默认相互转换就15次就会被移到老年代中。

你可能感兴趣的:(JVM运行时数据区)