JVM基础-Hotspot VM相关知识学习

2023-09-13 09:34:04

JVM参考文章:

JVM之 方法区、永久代(PermGen space)、元空间(Metaspace)三者的区别

jdk

JRE是java运行时环境而JDK是java开发工具包,JDK包含JRE,但是JRE可以独立安装。

  • JDK:java development kit (java开发工具),JDK 是用于开发 Java 程序的最小环境。

  • JRE:java runtime environment (java运行时环境),是提供给 Java 程序运行的最小环境。

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

在这里插入图片描述

JVM虚拟机

在这里插入图片描述

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

在这里插入图片描述

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

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

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

  • 动态链接(虚方法)发生在运行时,静态链接发生在编译时(private\static\final)

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

JVM知识梳理之二_JVM的常量池

在这里插入图片描述

类的生命周期

在这里插入图片描述

类加载的时机

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

  • 当虚拟机启动时加载主类。
  • 使用 java . lang . reflect 包的方法对类进行反射调用时,如果类还没有初始化,则需要进行初始化。
  • new 一个类的对象,调用类的静态成员(除了由 final 修饰的常量外)和静态方法,无论是解析执行还是编译执行的情况下,都会在处理 new 、 getstatic 、 putstatic 或 invokestatic 字节码指令时对类进行初始化。在第9章中会介绍使用 new 字节码指令创建对象的过程,其中就会有触发类装载的逻辑判断。
  • 当初始化一个类时,如果其父类没有被初始化,则先初始化其父类。后续在介绍函数 InstanceKlass :: initialize _ impl ()时会看到这个判断逻辑。
  • 使用JDK7的动态语言支持时,如果一个 java . lang . invoke . MethodHandle 对象最后的解析结果是 REF _ getStatic 、 REF _ putStatic 和 REF _ invokeStatic 的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先进行初始化。

可以通过调用 ClassLoader 类的 loadClass ()方法装载类,还可以调用 java . lang . Class .
forName ()方法通过反射的方式完成装载类。 loadClass ()方法只是将 Class 文件装载到 HotSpot VM 中,而 forName ()方法会完成类的装载、链接和初始化过程。

类的双亲委派机制

各个类加载器之间并不是继承关系,而是表示工作过程,具体说就是,对于一个加载类的具体请求,首先要委派给自己的父类加载器去加载,只有父类加载器无法完成加载请求时子类加载器才会尝试加载,这就叫"双亲委派"。
在这里插入图片描述

在这里插入图片描述

类的验证

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

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

在这里插入图片描述
在这里插入图片描述

全网最硬核 JVM TLAB(Thread Local Allocate Buffer) 分析

java对象

在这里插入图片描述
在这里插入图片描述

Mark Word

32位Mark Word:
在这里插入图片描述

64位Mark Word:
在这里插入图片描述

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

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

实例数据

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

对齐数据

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

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

在这里插入图片描述
默认情况下JVM开启了指针压缩,对象A大小情况

  • 【Mark word】为8字节
  • 【Klass Pointer】被压缩为4字节
  • 实例数据:int类型id大小为4字节、String类型name大小为4字节、byte类型b大小为1字节,byte类型对象内对齐3字节、Object类型o大小为4字节
  • 对齐填充:综上数据大小为28字节,数据对齐添加4字节,对象A的实际大小为32字节

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

在这里插入图片描述
手动关闭JVM指针压缩,对象A大小情况

  • 【Mark word】为8字节
  • 【Klass Pointer】为8字节
  • 实例数据:int类型id大小为4字节、String类型name大小为8字节、byte类型b大小为1字节,byte类型对象内对齐3字节、Object类型o大小为8字节
  • 对齐填充:综上数据大小为40字节,数据对齐不用补齐,对象A的实际大小为40字节

Java对象中实例数据发生的间隙填充alignment/padding gap条件是什么?

字符串常量池

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

垃圾收集器

在这里插入图片描述
在这里插入图片描述

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

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

Serial 收集器是一个单线程的收集器,采用"复制"算法。单线程的意义一方面指它
只会使用一个 CPU 或一条收集线程去完成圾收集工作,另一方面指在进行垃圾收集时必须暂停其他的工作线程,直到收集结束。
Serial 收集器的工作过程如图所示。
在这里插入图片描述

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

cms垃圾算法

在这里插入图片描述

G1垃圾收集器

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

关于垃圾收集器G1与ZGC

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述
1.长期存活的对象进入老年代

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

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

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

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

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

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

触发 GC 的流程如图所示。
在这里插入图片描述
JVM随笔 — 安全点(safe point)与 安全区域( safe region)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

更多推荐

【实战】 七、Hook,路由,与 URL 状态管理(下) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(十三)

文章目录一、项目起航:项目初始化与配置二、React与Hook应用:实现项目列表三、TS应用:JS神助攻-强类型四、JWT、用户认证与异步请求五、CSS其实很简单-用CSS-in-JS添加样式六、用户体验优化-加载中和错误状态处理七、Hook,路由,与URL状态管理1+2.3~67.完成URL状态管理与JS中的iter

GO学习之切片操作

GO系列1、GO学习之HelloWorld2、GO学习之入门语法3、GO学习之切片操作4、GO学习之Map操作5、GO学习之结构体操作6、GO学习之通道(Channel)7、GO学习之多线程(goroutine)8、GO学习之函数(Function)9、GO学习之接口(Interface)10、GO学习之网络通信(Ne

RL — 强化学习算法概述

一、说明在本系列中,我们检查了许多强化学习(RL)算法,例如,MoJoCo任务的策略梯度方法,Atari游戏的DQN和机器人控制的基于模型的RL。虽然许多算法都是针对特定领域引入的,但这种联系只能是遗留的。在本文中,我们将概述这些算法,并讨论它们在选择使用什么方法时的一般权衡。二、无模型算法RL算法可分为基于模型的算法

飞书ChatGPT机器人 – 打造智能问答助手实现无障碍交流

文章目录前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10.机器人测试前言在飞书中创建chatGPT机器人并且对话,在下面操作步骤中,使用

静态代码分析基础知识及分析工具

安全之安全(security²)博客目录导读ATF(TF-A)/OPTEE之静态代码分析汇总目录一、静态代码分析介绍二、静态代码分析工具三、Sonarlint静态代码分析工具介绍1.定义2.特性3.SonarQube的官方文档一、静态代码分析介绍根据维基百科,静态代码检查又称为静态程序分析,是指在不运行计算机程序的条件

WAIC2023:图像内容安全黑科技助力可信AI发展

目录0写在前面1AI图像篡改检测2生成式图像鉴别2.1主干特征提取通道2.2注意力模块2.3纹理增强模块3OCR对抗攻击4助力可信AI向善发展总结0写在前面2023世界人工智能大会(WAIC)已圆满结束,恰逢全球大模型和生成式人工智能蓬勃兴起之时,今年参会的人们更加关注AIGC技术在未来可以如何作用于人们的生活。自AI

公网访问的Linux CentOS本地Web站点搭建指南

文章目录前言1.本地搭建web站点2.测试局域网访问3.公开本地web网站3.1安装cpolar内网穿透3.2创建http隧道,指向本地80端口3.3配置后台服务4.配置固定二级子域名5.测试使用固定二级子域名访问本地web站点前言在web项目中,部署的web站点需要被外部访问,则需要一个媒介,通过把资源放在这个媒介中

PSO粒子群优化算法

PSO粒子群优化算法算法思想matlab代码python代码算法思想粒子群算法(ParticleSwarmOptimization)优点:1)原理比较简单,实现容易,参数少。缺点:1)易早熟收敛至局部最优、迭代后期收敛速度慢的。算法拓展针对标准PSO的缺点,通常有如下的改进:实现参数的自适应变化。引入一些其他机制。比如

Mysql和ES、Redis数据同步方案汇总

文章目录前言一、数据同步方案1.同步双写2.异步双写([MQ](https://so.csdn.net/so/search?q=MQ&spm=1001.2101.3001.7020)方式)3.基于Mysql表定时扫描同步4.基于[Binlog](https://so.csdn.net/so/search?q=Binlo

AIGC数据处理与存储解决方案

针对在AIGC的场景下,如何解决在AIGC训练过程中数据的存储和数据处理的问题,杨冠军从三个方面进行介绍与解读:一是AIGC对存储提的新需求;二是介绍腾讯云可以给用户提供的整体存储解决方案;三是腾讯云提供的整体数据处理方案。AIGC的新需求:模型训练与应用推理的述求我国每年产生的数据量呈现非常大的增长趋势,这个前提还是

【JavaSE笔记】继承与多态(万字详解)

一、前言在Java的核心概念中,继承和多态无疑是重要的一环。它们都是Java以及其他许多面向对象编程语言的基石,为我们提供了强大的工具来创建模块化,可重用和易于维护的代码。继承让我们可以创建新的类,通过继承现有类的属性和方法,来复用代码并添加或覆盖特定的行为。这为我们提供了一种强大的方式来组织和结构化我们的代码,使我们

热文推荐