联系我们
简单又实用的WordPress网站制作教学
当前位置:网站首页 > 程序开发学习 > 正文

Jvm基础-热点vm相关知识学习

作者:小教学发布时间:2023-09-19分类:程序开发学习浏览:82


导读:这里写目录标题JDKJvm虚拟机类类的生命周期类加载的时机类的双亲委派机制类的验证JAVA对象标记单词Klass指针实例数据对齐数据字符串常量池垃圾收集器1.串口收集器(串行收集器...

这里写目录标题

    • JDK
    • Jvm虚拟机
      • 类的生命周期
      • 类加载的时机
      • 类的双亲委派机制
      • 类的验证
    • JAVA对象
          • 标记单词
          • Klass指针
          • 实例数据
          • 对齐数据
    • 字符串常量池
    • 垃圾收集器
      • 1.串口收集器(串行收集器)
      • 不育系垃圾算法
      • G1垃圾收集器
          • 与CMS收集器相比,G1收集器的优势:
          • G1收集器的实现原理:

Jvm参考文章:

Jvm之方法区、永久代(永久生成空间)、元空间(元空间)三者的区别

JDK

Jre是Java运行时环境而jdk是Java开发工具包,jdk包含jre,但是jre可以独立安装。

  • Jdk:Java开发工具包(Java开发工具),jdk是用于开发Java程序的最小环境。

  • JAVA运行时环境(Java运行时环境),是提供给JAVA程序运行的最小环境.

Jre包含了Java虚拟机、Java基础类库。是使用Java语言编写的程序运行所需要的软件环境,是提供给想运行Java程序的用户使用的。Jdk是程序员使用Java语言编写Java程序所需的开发工具包,是提供给程序员使用的。运行Java程序只需安装Jre.如果需要编写Java程序,需要安装jdk。

Jvm基础-热点vm相关知识学习

Jvm虚拟机

Jvm基础-热点vm相关知识学习

  • 内存模型中线程独享的有:线程栈(虚拟机栈)、本地方法栈、程序计数器
  • 内存模型中线程共享的有:堆、方法区(1.7以前名为永久区,1.8后为元空间)
  • 常量池中的对象在1.6以前位于用永久区,1.7以后位于
  • 线程栈的最小单元叫栈帧,组成部分有局部变量表、操作数栈、动态链接、方法出口

Jvm基础-热点vm相关知识学习

  • 在方法区里面有一个运行常量池,包含变量和方法、文件所有的变量和引用作为符号引用,保存在类、文件的常量池中类。

  • 描述一个方法调用了其他的方法的时候就是通过常量池中指向方法的符号引用来表示.那么动态连接的作用就是将这些符号引用转化成调用方法的直接引用

  • 所以动态链接:将对方法的符号引用链接成对调用方法的直接引用

  • 动态链接(虚方法)发生在运行时,静态链接发生在编译时(私有\静态\最终)

  • 重载是静态绑定,重写是动态绑定

Jvm知识梳理之二_jvm的常量池

Jvm基础-热点vm相关知识学习

类的生命周期

Jvm基础-热点vm相关知识学习

类加载的时机

下面5种情况下会导致类初始化,因此必须在发生这5种情况之前对类进行加载.

  • 当虚拟机启动时加载主类.
  • 使用Java。朗。反映包的方法对类进行反射调用时,如果类还没有初始化,则需要进行初始化。
  • New一个类的对象,调用类的静态成员(除了由Final修饰的常量外)和静态方法,无论是解析执行还是编译执行的情况下,都会在处理New、GetStatic、PutStatic或Invookestatic字节码指令时对类进行初始化。在第9章中会介绍使用新字节码指令创建对象的过程,其中就会有触发类装载的逻辑判断。
  • 当初始化一个类时,如果其父类没有被初始化,则先初始化其父类.后续在介绍函数实例类::初始化_执行()时会看到这个判断逻辑。
  • 使用jdk7的动态语言支持时,如果一个Java。朗。召唤。方法处理对象最后的解析结果是ref_getStatic、ref_put静态和ref_的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先进行初始化。

可以通过调用类加载器类的LoadClass()方法装载类,还可以调用Java。朗。同学们。
ForName()方法通过反射的方式完成装载类。LoadClass()方法只是将类文件装载到热点VM中,而名称()方法会完成类的装载、链接和初始化过程。

类的双亲委派机制

各个类加载器之间并不是继承关系,而是表示工作过程,具体说就是,对于一个加载类的具体请求,首先要委派给自己的父类加载器去加载,只有父类加载器无法完成加载请求时子类加载器才会尝试加载,这就叫“双亲委派”。
Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

类的验证

类在连接过程中会涉及验证.HotSpot VM会遵守JAVA虚拟机的规范,对类文件中包含的信息进行合法性验证,以保证HotSpot VM的安全。从整体上看,大致进行如下4方面的验证.

  • 文件格式验证:包括魔数和版本号等;
  • 元数据验证:对程序进行语义分析,如是否有父类,是否继承了不被继承的类,是否实现了父类或者接口中所有要求实现的方法;
  • 字节码验证:指令级别的语义验证,如跳转指令不会跳转到方法体以外的代码上;
  • 符号引用验证:符号引用转化为直接引用的时候,可以看作对类自身以外的信息进行匹配验证,如通过全限定名是否能找到对应的类等.

Jvm基础-热点vm相关知识学习
Jvm基础-热点vm相关知识学习
Jvm基础-热点vm相关知识学习
全网最硬核JVMTLAB(线程本地分配缓冲区)分析

JAVA对象

Jvm基础-热点vm相关知识学习
Jvm基础-热点vm相关知识学习

标记单词

32位标记字:
Jvm基础-热点vm相关知识学习

64位标记字:
Jvm基础-热点vm相关知识学习

  • 锁标志位(Lock):区分锁状态,11时表示对象待GC回收状态,只有最后2位锁标识(11)有效.
  • BIASSED_LOCK:是否偏向锁,由于正常锁和偏向锁的锁标识都是01,没办法区分,这里引入一位的偏向锁标识位。
  • 分代年龄(年龄):表示对象被GC的次数,当该次数到达阈值(最大为15,默认为15,CMS垃圾收集器默认为6)的时候,对象就会转移到老年代。
  • 对象的哈希码(HASH):运行期间调用系统.标识哈希码()来计算,延迟计算,并把结果赋值到这里.当对象加锁后,计算的结果31位不够表示,在偏向锁,轻量锁,重量锁,哈希码会被转移到监视器中。
  • 偏向锁的线程ID(Java线程):偏向模式的时候,当某个线程持有对象的时候,对象这里就会被置为该线程的ID。在后面的操作中,就无需再进行尝试获取锁的动作.
  • 纪元:偏向锁在CAS锁操作过程中,偏向性标识,表示对象更偏向哪个锁。
  • Ptr_to_Lock_Record:轻量级锁状态下,指向栈中锁记录的指针。当锁获取是无竞争的时、jvm使用原子操作而不是OS互斥。这种技术称为轻量级锁定.在轻量级锁定的情况下,jvm通过cas操作在对象的标题字中设置指向锁记录的指针.
  • Ptr_to_HeavyWeight_MONITOR:重量级锁状态下,指向对象监视器显示器的指针。如果两个不同的线程同时在同一个对象上竞争,则必须将轻量级锁定升级到监视器以管理等待的线程。在重量级锁定的情况下,jvm在对象的ptr_to_Heavyweight_设置指向监视器的指针。
Klass指针

即类型指针,是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例.

实例数据

如果对象有属性字段,则这里会有数据信息.如果对象无属性字段,则这里就不会有数据.根据字段类型的不同占不同的字节,例如boolean类型占1个字节,int类型占4个字节等等;

对齐数据

对象可以有对齐数据也可以没有.默认情况下、JAVA虚拟机堆中对象的起始地址需要对齐至8的倍数。如果一个对象用不到8N个字节则需要对其填充,以此来补齐对象头和实例数据占用内存之后剩余的空间大小。如果对象头和实例数据已经占满了jvm所分配的内存空间,那么就不用再进行对齐填充了。
所有的对象分配的字节总Size需要是8的倍数,如果前面的对象头和实例数据占用的总Size不满足要求,则通过对齐数据来填满。

为什么要对齐数据?
字段内存对齐的其中一个原因,是让字段只出现在同一cpu的缓存行中。如果字段不是对齐的,那么就有可能出现跨缓存行的字段.也就是说,该字段的读取可能需要替换两个缓存行,而该字段的存储也会同时污染两个缓存行.这两种情况对程序的执行效率而言都是不利的.其实对其填充的最终目的是为了计算机高效寻址.

Jvm基础-热点vm相关知识学习
默认情况下jvm开启了指针压缩,对象A大小情况

  • [标记Word]为8字节
  • [克拉斯指针]被压缩为4字节
  • 实例数据:Int类型id大小为4字节、String类型Name大小为4字节、Byte类型b大小为1字节,字节类型对象内对齐3字节、Object类型o大小为4字节
  • 对齐填充:综上数据大小为28字节,数据对齐添加4字节,对象A的实际大小为32字节

新对象()生成的对象大小为16个字节

Jvm基础-热点vm相关知识学习
手动关闭jvm指针压缩,对象A大小情况

  • [标记Word]为8字节
  • [克拉斯指针]为8字节
  • 实例数据:Int类型id大小为4字节、String类型Name大小为8字节、Byte类型b大小为1字节,字节类型对象内对齐3字节、Object类型o大小为8字节
  • 对齐填充:综上数据大小为40字节,数据对齐不用补齐,对象A的实际大小为40字节

JAVA对象中实例数据发生的间隙填充对齐/填充间隙条件是什么?

字符串常量池

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

垃圾收集器

Jvm基础-热点vm相关知识学习
Jvm基础-热点vm相关知识学习

图中的连线表示可以使用连线两端的两种收集器分别收集年轻代和老年代的内存空间,而G1收集器既以收集年轻代的内存空间,也可以收集老年代的内存空间.

1.串口收集器(串行收集器)

串口收集器是一个单线程的收集器,采用“复制”算法。单线程的意义一方面指它
只会使用一个cpu或一条收集线程去完成圾收集工作,另一方面指在进行垃圾收集时必须暂停其他的工作线程,直到收集结束。
串口收集器的工作过程如图所示。
Jvm基础-热点vm相关知识学习

串口收集器是一个单线程的收集器,采用“复制”算法.“单线程”并不是说只使
用一个cpu或一条收集线程去完成垃圾收集工作,而是指在进行垃圾收集时,必须暂停其他的工作线程,直到收集结束。本章将详细介绍串口垃圾回收的具体实现过程。

不育系垃圾算法

Jvm基础-热点vm相关知识学习

G1垃圾收集器

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

与CMS收集器相比,G1收集器的优势:
  • 基于标记-整理算法,不会产生大量的内存碎片;
  • 可以更加精确地控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收.
G1收集器的实现原理:
  • G1收集器能够避免全区域的垃圾收集,它把堆内存划分为大小固定的几个独立区域,并跟踪这些区域的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾最多的区域

Jvm基础-热点vm相关知识学习

关于垃圾收集器G1与ZGC

Jvm基础-热点vm相关知识学习

  • 默认情况下年轻代所占内存为堆空间的1/3、其中Eden区大小占年轻代空间的80%、S0和S1各占10%;永久代所占内存为堆空间的2/3

Jvm基础-热点vm相关知识学习

STW的原因?
防止少标或多标(多标产生浮动垃圾)

Jvm基础-热点vm相关知识学习
1.长期存活的对象进入老年代

幸存区复制一次,则年龄增加1.当对象的年龄达到设定的阈值时,将会晋升到老年代.默认情况下,并行GC的年龄阈值为15,并发GC的年龄阈值为6。由于AGE只有4位,所以最大值为15,这就是-XX:MaxTenuring Threshold选项最大值为15的原因.

虚拟机给每个对象定义了一个对象年龄计数器.如果对象在Eden空间分配并经过第
一次YGC后仍然存活,在将对象移动到to Survivor空间后对象年龄会设置为1.对象在Survivor空间每熬过一次,YGC年龄就加一岁,当它的年龄增加到一定程度(默认为15岁)时,就会晋升到老年代中对象晋升老年代的年龄阈值,可以通过-XX:最大延时-阈值选项来设置。类中定义表TABLE_SIZE数组的大小为16,由于通过-XX:最大租期阈值选项可设置的最大年龄为15,所以数组的大小需要设置为16,因为还需要通过SIZES[0]表示一次都未移动的对象,不过实际上不会统计SIZES[0],因为SIZES[0]
的值一直为0。

2.动态对象年龄判定
为了能更好地适应不同程度的内存状况,虚拟机并不总是要求对象的年龄必须达到最大延时阈值才能晋升到老年代。如果在幸存者空间中小于等于某个年龄的所有对象空间的总和大于幸存者空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。因此需要通过调整数组统计年轻代中各个年龄对象的总空间的大小。

3.触发YGC
大多数情况下,对象直接在年轻代中的Eden空间进行分配,如果Eden区域没有足够的空间,那么就会触发ygc(Minor GC,年轻代垃圾回收),Ygc处理的区域只有年轻代.下面结合年轻代对象的内存分配看一下触发YGC的时机:

  • 新对象会先尝试在栈上分配,如果不行则尝试在TLab中分配,否则再看是否满足大对象条件可以在老年代分配,最后才考虑在Eden区申请空间.
  • 如果Eden区没有合适的空间,则HotSpot VM在进行YGC之前会判断老年代最大的可用连续空间是否大于新生代的所有对象的总空间,具体判断流程如下:
    1. 如果大于的话,直接执行ygc.
    2. 如果小于,则判断是否开启了句柄促销失败,如果没有开启则直接执行
      FGC。
    3. 如果开启了HandlePromotionFailure,HotSpot VM会判断老年代的最大连续内存空间是否大于历次晋升的平均内存空间(晋级老年代对象的平均内存空间),如果小于则直接执行FGC;如果大于,则执行YGC。

对于HandlePromotionFailure,我们可以这样理解,在发生Ygc之前,虚拟机会先检查老年代的最大的连续内存空间是否大于新生代的所有对象的总空间,如果这个条件成立,则Ygc是安全的.如果不成立,虚拟机会查看Handle Promotions Failure设置值是否允许判断失败,如果允许,那么会继续检查老年代最大可用的连续内存空间是否大于历次晋级到老年代对象的平均内存空间,如果大于就尝试一次YGC、如果小于,或者Handle-Promotion Failure不愿承担风险就要进行一次FGC。

触发GC的流程如图所示.
Jvm基础-热点vm相关知识学习
Jvm随笔-安全点(安全点)与安全区域(安全区)

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习

Jvm基础-热点vm相关知识学习





程序开发学习排行
最近发表
网站分类
标签列表