JVM中的运行时数据区

主要记录JVM里面的运行时数据区的知识,包括程序计数器,Java虚拟机栈,本地方方法栈,运行时方法区,堆相关知识;Java虚拟机栈中的栈帧介绍,堆中分区划代,各个分区如何工作,垃圾回收机制在各个分区如何工作

知识图谱:
在这里插入图片描述


一、运行时数据区

主要处理Java程序在运行的时候产生的数据,并进行处理
主要包括:

  1. 程序计数器
  2. Java虚拟机栈
  3. 本地方法栈
  4. 运行时方法区

1.程序计数器

是Java中占用很小的一块内存区间,也是不会发生内存溢出的区间。主要是用来记录线程将要执行指令的位置,是线程独立的,生命周期与线程保持一致

2.Java虚拟机栈

Java虚拟机栈是一个运行时单位,负责Java程序在执行方法时,记录执行的方法信息,当有一个方法执行的时候,就会发生压栈操作,存储该方法信息的地方称之为栈帧,当方法执行完毕后,就会出栈,是线程独立的

栈帧的内部结构:

  1. 局部变量表
    是一组变量值存储空间,用于存放方法参数与方法内部定义的局部变量。对于基本数据类型的变量,则直接存储它的值,对于引用数据类型,则存储指向对象的引用
  2. 操作数栈
    栈最典型的一个应用是对表达式求值。在一个线程执行方法的过程中,实际上就是不断执行语句的过程,归根结底就是进行计算的过程,所以可以这样子说:计算机所有的计算过程都是由操作数栈实现的
  3. 动态链接
    指向运行时常量池的方法引用,方法的调用地址。方法在运行的时候,会用到类中的常量(为类中属性最开始定义的数据),所以必须要有一个引用指向运行时常量
  4. 方法返回地址
    当一个方法执行完毕之后,需要返回到调用它的地方,因此必须在栈帧中保存一个方法返回地址

3.本地方法栈

在Java中使用Native修饰的方法就是本地方法,也就是操作系统的方法,如果调用了本地方法,则把这些本地方法放在本地方法栈中运行,是线程独立的;内存的空间大小可以调整;可能会出现栈溢出

4.堆

堆是一块用于存储JVM里面对象的内存空间,物理上不连续,逻辑上连续;是内存管理的核心区域,也是JVM里面管理的最大一块空间,是垃圾回收的重点区域,堆空间是线程共享的

4.1 分区目的

分区的目的是便于垃圾回收,因为对象的存活时间各不相同,当我们进行垃圾回收的时候,应该选择不同的算法回收对象垃圾,实现比较优的垃圾回收效果

堆的分区:分为新生代与老年代

新生代区又分为:

  1. 伊甸园区
    用于存储新创建的对象
  2. 幸存者区
    用于存储每次经过垃圾回收之后伊甸园区没有被回收的对象;幸存者区域分为两块,一块是s0区域,一块是s1区域,也可以称之为from区与to区

4.2 垃圾回收在堆中的运行过程

假设现在的新生代与老年代都是空的,我们此时创建一个对象,堆会在伊甸园区存储这个对象,当发生垃圾回收之后,如果这个对象没有被回收,伊甸园区的这个对象会被放到幸存者区域s0,并且会在这个对象的对象头区域(分配了4bit)存储它的移动次数,此时会将移动次数变为1;下一次发生垃圾回收之后,如果这个对象没有被回收,则会将它从s0区域移动到s1区域。这个过程中,始终保持着幸存者区域的两个分区有一个分区保持空白,并且伊甸园区是始终存储着新创建对象信息

在刚才的假设上发生点变化,我们一共创建两个对象。第一个对象现在已经被存储在了s0区域,此时创建第二个对象,那么它的变化会是怎样的?当第二个对象被创建后,会被存储在伊甸园区,发生垃圾回收之后,是垃圾的对象,会被移出内存,不是垃圾,则会将这个对象移到s1区域,但是此时s0区域还有一个对象,我们还要保证s0与s1存在一个空白区域,则此时,会检测s0区域的对象,是垃圾则回收,不是垃圾则将它从s0区域移入到s1区域。每发生一次移动都会将对象头信息进行修改,如果移动次数成了15,则将幸存者区域的对象存储到老年代区域

4.3 分区大小

新生代与老年代默认的比率是1:2-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整个堆空间的1/3;如果生命周期长的对象较多时,可以调整这个参数进行调优

伊甸园区存储着新生的对象,这块区域较大;幸存者区域不停地发生着清空与移动,所以这块区域内存大小较小

伊甸园区与两个幸存者区默认是8:1:1-XX:SurvivorRatio=8,表示伊甸园区占新生代区域的8/10

在默认参数下对象经过15次垃圾回收依然存活会去老年代;参数最大值是15

4.4 分代收集思想:

JVM中的垃圾回收可以根据不同的区域进行回收,主要包括Minor GC,Major GC,Full GC;
JVM在进行垃圾回收的时候,分为部分收集与整堆收集;部分收集主要针对的是新生代与老师代的堆空间,整堆收集朱要针对整个方法区与堆

部分收集: 分别对堆空间里面的新生代区域与老年代区域进行垃圾回收

  1. 新生代收集(Minor GC/Yong GC):主要收集伊甸园区与幸存者区垃圾
  2. 老年代收集(Major GC/Old GC):主要收集老年代区垃圾

整堆收集:(Full GC):收集整个Java堆与方法区垃圾

整堆收集出现的情况:

  1. System.gc()时
  2. 老年区空间不足
  3. 方法区空间不足

应该尽量避免出现整堆收集

字符串常量池在JDK1.7之后的位置由方法区转移到了堆中,因为方法区垃圾回收只会在Full GC的时候才会被回收,效率较低

4.5 堆空间参数设置

官网地址:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

-XX:+PrintFlagsInitial 查看所有参数的默认初始值
-XX:+PrintFlagsFinal 查看所有参数的最终值(修改后的值)
-Xms:初始堆空间内存(默认为物理内存的 1/64)
-Xmx:最大堆空间内存(默认为物理内存的 1/4)
-Xmn:设置新生代的大小(初始值及最大值)
-XX:NewRatio:配置新生代与老年代在堆结构的占比
-XX:SurvivorRatio:设置新生代中 Eden 和 S0/S1 空间比例
-XX:MaxTenuringTreshold:设置新生代垃圾的最大年龄
-XX:+PrintGCDetails 输出详细的 GC 处理日志

5.运行时方法区

主要存储类信息,如静态常量,静态变量,方法属性;运行时常量池

运行时常量池主要记录类中的常量数值信息(字面量值,符号引用)

方法区是线程共享,也可能出现内存溢出,也会涉及垃圾回收
方法区在JVM启动后就会被创建,方法区的大小决定了系统中可以保存多少类
方法区默认的大小是21M,当内存大小达到21M后,会触发FUll GC,进行回收内存,方法区大小可以设置为 -1,表示内存大小无限制

方法区垃圾回收主要涉及:静态常量以及类信息

类信息回收要满足3个条件

  1. 该类的子类都已经被回收
  2. 改类的java.lang.Class对象已经不被其他地方引用
  3. 改类的类加载器已经被回收
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

The CrazyMan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值