JVM知识总结

news2024/10/1 7:36:37

1.概述

JVM指的是Java虚拟机,本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件,作用是为了支持跨平台特性。

功能:

  1. 装载字节码,解释/编译为机器码

  2. 管理数据存储和垃圾回收

  3. 优化热点代码提升效率

2.构成

  1. 类加载子系统:从硬盘上加载字节码文件到JVM

  2. 运行时方法区:按照不同的数据分区存储(方法区,栈,堆,本地方法栈,程序计数器)

  3. 执行引擎:将字节码再次编译/解释为机器码

  4. 本地库接口:负责调用本地方法

3.类加载子系统

3.1加载

  1. 通过类的全限类名获得此类的二进制字节流

  2. 将静态存储转化为运行时存储(方法区)

  3. 在内存中生成该类的class对象

3.2链接

验证:检验被加载的字节码是否正确

1.文件格式验证,比如文件是否以0xCAFEBABE开头,主次版本号是否满足当前Java虚拟机版本要求。 2.元信息验证,例如类必须有父类(super不能为空)。 3.验证程序执行指令的语义,比如方法内的指令执行到一半强行跳转到其他方法中去。 4.符号引用验证,例如是否访问了其他类中private的方法等。

准备:为该类的静态属性分配内存,并设置默认值(不包括被final修饰,此时会直接赋值,因为在编译时就被加载)

解析:将常量池中二进制的符号引用替换成直接引用,符号引用就是在字节码文件中使用编号来访问常量池中 的内容。直接引用不在使用编号,而是使用内存中地址进行访问具体的数据。

3.3初始化

为类的静态变量赋初值,执行字节码文件中clint部分的字节码指令

3.4类初始化时机

  1. 使用类中的静态变量,静态方法

  2. 创建对象

  3. 运行main方法

  4. 反射

  5. 初始化子类

4.运行时数据区

4.1程序计数器

记录程序执行的位置,不会出现内存溢出的情况,内存小,速度快,是线程私有的,不会进行垃圾回收

4.2虚拟机栈

一个方法入栈后,可以看作是一个栈帧

  • 局部变量表:存放方法的参数和局部变量

  • 操作数栈:在执行指令时用来存放临时数据的一块区域

  • 返回地址:当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保 存一个方法返回地址。

4.3本地方法栈

存放本地方法,线程私有,会造成内存溢出,不会进行垃圾回收.

本地方法:被native修饰的方法,没有方法体,例如

native hashCode() 内存地址 native getClass(); native Object clone() native void notify(); native void notifyAll(); native void wait(long timeout) FileInputStream native int read0() Thread native void start0();

4.4堆

存放程序中的对象实例,共享线程,会内存溢出,会进行垃圾回收,是JVM管理最大的一块内存空间

  • 分区

为什么分区?

根据存活时间的长短进行划分,生命较长的对象放在老年代减少垃圾回收次数和扫描频率

对象分区流程

  1. 新创建的对象存放在伊甸园区

  2. 当垃圾回收时,将伊甸园存活的对象移入到幸存者0区

  3. 再次创建的新对象还是在伊甸园区

  4. 下一次垃圾回收到来时会将伊甸园区存货的对象和幸存者0存活的对象转至幸存者1区,始终保持幸存者区有一个是空的

  5. 当一个对象经过15次垃圾回收后仍然存活,该对象被移入老年区

  6. 当老年代中空间不足,无法放入新的对象时,先尝试major gc如果还是不足,就会触发Full GC,Full GC会对整个堆进行垃圾回收。

4.5方法区

在不同的hotspot版本中会使用永久代和元空间来实现主要包括:

  1. 每一个加载的类的基本信息

  2. 运行时常量池,保存了字节码文件中的常量池信息

    大小可调节并且线程是共享的,但会造成内存溢出

5.本地方法接口

底层由非Java代码实现,并不提供方法体,由于高级语言无法直接访问底层的硬件,所以需要调用操作系统提供的接口进行访问。

6.执行引擎

将装载到虚拟机的字节码编译为机器码

  • 前端编译:.java---->.class

  • 后端编译:.class---->机器码

6.1解释执行

用一个解释器对代码逐行进行解释,一般用于脚本语言(效率低,但省去了编译时间)

6.2编译执行

一次性的对代码进行整体编译(编译费时,但执行效率高)

6.3解释器和JIT编译器

  • 解释器:当 Java 虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。

  • JIT(Just In Time Compiler)编译器:就是虚拟机将源代码一次性直接编译成和本地机器平台相关的机器语言,但并不是马上执行。

在Java中采用半解释半编译的方式将字节码转化为机器码,程序刚开始执行时解释器就会立即执行,但在运行过程中,会将热点代码编译并缓存,二者结合达到一个平衡点

7.JDK6-8内存区域的区别

7.1方法区的实现

使用元空间替换永久代的原因: 1、提高内存上限:元空间使用的是操作系统内存,而不是JVM内存。如果不设置上限,只要不超过操作系统内存 上限,就可以持续分配。而永久代在堆中,可使用的内存上限是有限的。所以使用元空间可以有效减少OOM情况 的出现。 2、优化垃圾回收的策略:永久代在堆上,垃圾回收机制一般使用老年代的垃圾回收方式,不够灵活。使用元空间 之后单独设计了一套适合方法区的垃圾回收机制

7.2字符串常量池的位置

字符串常量池从方法区移动到堆的原因: 1、垃圾回收优化:字符串常量池的回收逻辑和对象的回收逻辑类似,内存不足的情况下,如果字符串常量池中的 常量不被使用就可以被回收;方法区中的类的元信息回收逻辑更复杂一些。移动到堆之后,就可以利用对象的垃圾 回收器,对字符串常量池进行回收。 2、让方法区大小更可控:一般在项目中,类的元信息不会占用特别大的空间,所以会给方法区设置一个比较小的 上限。如果字符串常量池在方法区中,会让方法区的空间大小变得不可控。 3、intern方法的优化:JDK6版本中intern () 方法会把第一次遇到的字符串实例复制到永久代的字符串常量 池中。JDK7及之后版本中由于字符串常量池在堆上,就可以进行优化:字符串保存在堆上,把字符串的引用放入 字符串常量池,减少了复制的操作

8.类加载器

类加载器负责在类的加载过程中将字节码信息以流的方式获取并加载到内存中

1.启动类加载器

JDK9之前由C++编写,JDK9之后由Java编写

2.拓展类加载器

JDK提供的,使用Java编写的加载器,派生于 ClassLoader 类.

3.应用类加载器

加载我们自己定义的类,用于加载用户类路径(classpath)上所有的类

4.自定义加载器

我们自己写一个类继承ClassLoder再例如tomcat这种容器,都会有自己加载类的加载器,重写findClass方法。

9.双亲委派机制

双亲委派机制指的是:当一个类加载器接收到加载类的任务时,会向上查找是否加载过,再由顶向下进行加载。如果上级找不到,就逐级向下委托,使用子级类加载器加载的类,如果都找不到,就报异常了。

作用:

  1. 保证类加载的正确性避免恶意代码来替代系统类库中的类,比如java.lang.String

  2. 避免同一个类被重复加载

9.1如何打破

实现自定义类加载器重写findClass()方法,将其中双亲委派机制的代码删除

10.垃圾回收

没有任何引用指向的对象,一直占用内存空间知道程序结束,被保留的空间的无法对其他对象使用,严重的会导致内存溢出。早期的垃圾回收:c/c++程序员手动在程序中对不使用的对象进行删除,如果忘记回收会造成内存泄漏

10.1内存溢出和内存泄漏

  • 内存溢出:垃圾回收速度跟不上内存占用的速度

  • 内存泄漏:对于对象不被使用,但GC无法回收的对象,导致OOM,是内存溢出的原因之一

例如:数据库连接 dataSourse.getConnection(),网络连接 socket 和 io 连接必须手动 close,否则是不能被回收的。

10.2STW

Stop-the-World,简称 STW,指的是 GC 事件发生过程中,会产生应用程序的停顿。当进行垃圾回收时,会导致其他用户线程暂停。可达性分析算法中枚举根节点(GC Roots)会导致所有 Java 执行线程停顿,为什么需要停顿所有 Java 执行线程?

  1. 分析工作必须在一个能确保一致性的快照中进行

  2. 一致性指整个分析期间整个执行系统看起来像被冻结在某个时间点上

  3. 如果出现分析过程中对象引用关系还在不断变化,则分析结果的准确性无法保 证,会出现漏标,错标问题

10.3标记阶段

主要是为了判断对象是否为垃圾对象

算法:

  1. 引用计数算法:被引用时+1。缺点:单独维护一个计数器,增加了内存空间占用,会造成循环引用

  2. 可达性分析算法:以根(GCRoots)为起点搜索被跟所连接的对象是否可达

10.3.1哪些对象被称之为GC Root对象

  • 线程Thread对象,引用线程栈帧中的方法参数、局部变量等。

  • 系统类加载器加载的java.lang.Class对象,引用类中的静态变量。

  • 监视器对象,用来保存同步锁synchronized关键字持有的对象。

  • 本地方法调用时使用的全局对象

10.3.2finalize方法

回收前调用,且只会调用一次,在被回收前此方法会执行一些需要的逻辑。由于 finalize()方法的存在,虚拟机中的对象一般处于三种可能的状态.

可触及的:从根节点开始,可以到达这个对象。 可复活的:对象的所有引用都被释放,但是对象有可能在 finalize()中复活。 不可触及的:对象的 finalize()被调用,并且没有复活,那么就会进入不可触及 状态。

以上 3 种状态中,是由于 finalize()方法的存在,进行的区分。只有在对象不可触及时才可以被回收

10.4回收阶段

标记-清除算法

概述:1.标记阶段:将存活对象进行标记,使用可达性分析算法寻找所有的存活对象

2.清除:删除没有别标记的对象

优点:操作简单,只需要维护标志位即可,无需进行对象的移动

缺点:会造成内存碎片化,很有可能这些内存单元的大小过小无法进行分配。由于内存碎片的存在,需要维护一个空闲链表,极有可能发生每次需要遍历到链表的最后才能获得合适的内存空间。

标记-复制算法

概述:准备两块空间,From和To,在对象分配期间只使用其中一块空间,GC阶段将From存活的对象复制到To中,再将两块空间名字互换

优点:不会造成内碎片,只需遍历一次,性能较好

缺点:会进行对象的移动,只有一半的空间来创建对象使用

标记-压缩算法

概述:1.标记阶段:将所有的存活对象的进行标记,使用可达性分析算法寻找所有的存活对象

2.整理阶段:将存活的对象移动到堆的一端

优点:内存利用率高,不会出现碎片化

缺点:造成对象移动,要选择合适的压缩算法

分区收集

  • 分代回收时,创建出来的对象,首先会被放入Eden伊甸园区。

  • 随着对象在Eden区越来越多,如果Eden区满,新创建的对象已经无法放入,就会触发年轻代的GC,称为Minor GC或者Young GC。Minor GC会把需要eden中和From需要回收的对象回收,把没有回收的对象放入To区

  • 如果Minor GC后对象的年龄达到阈值(最大15,默认值和垃圾回收器有关),对象就会被晋升至老年代。当老年代中空间不足,无法放入新的对象时,先尝试minor gc如果还是不足,就会触发Full GC,Full GC会对整个堆进行垃圾回收。

  • 如果Full GC依然无法回收掉老年代的对象,那么当对象继续放入老年代时,就会抛出Out Of Memory异常。

11.垃圾回收器

11.1Serial+SerialOld

Serial是是一种单线程串行回收年轻代的垃圾回收器。

11.2Parallel Scavenge+Parallel Old

PS+PO是JDK8默认的垃圾回收器,多线程并行回收,关注的是系统的吞吐量。具备自动调整堆内存大小的特点。

11.3ParNew

ParNew垃圾回收器本质上是对Serial在多CPU下的优化,使用多线程进行垃圾回收

11.4CMS(老年代)

CMS垃圾回收器关注的是系统的暂停时间,允许用户线程和垃圾回收线程在某些步骤中同时执行,减少了用户线程的等待时间。

优点:停顿时间少

缺点:使用标记-清除算法造成内存碎片较多

11.5G1

将每个区域(伊甸园,幸存者,老年代)又划分成若干个小的区域,哪个区域垃圾数量多,优先回收哪个区域,可以做到整堆管理收集也可以做到并发执行

未完待续......

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1402649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI技术图像编辑 Luminar Neo

Luminar Neo是一款先进的AI照片编辑软件,旨在简化和增强照片编辑过程。它适用于macOS和Windows,提供独立的应用程序以及用于集成到现有工作流程的插件。Luminar Neo的主要特点包括AI天空替换、Accent AI、氛围AI以及20多种独特的照片效果。无论是风景摄影…

Qt事件处理,提升组件类

1.相关说明 1.提升组件QLabel的类&#xff0c;以实现双击功能 2.监控键盘事件&#xff0c;实现上下左右移动 3.鼠标点击获取坐标 2.相关界面 3.相关代码和操作 自定义类TMyLabel&#xff0c;父类为QLabel tmylabel.h #ifndef TMYLABEL_H #define TMYLABEL_H #include <QL…

图像处理中,采用极线约束准则来约束特征点匹配搜索空间,理论上在极线上进行搜索。这里的极线是什么线,怎么定义的?基本矩阵F和本质矩阵E有什么区别?

问题描述&#xff1a;图像处理中&#xff0c;采用极线约束准则来约束特征点匹配搜索空间&#xff0c;理论上在极线上进行搜索。这里的极线是什么线&#xff0c;怎么定义的&#xff1f;基本矩阵F和本质矩阵E有什么区别&#xff1f; 问题1解答&#xff1a; 极线是通过极线几何学…

飞书+ChatGPT+cpolar搭建企业智能AI助手并实现无公网ip远程访问

文章目录 推荐 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂…

无线音频设备市场调研:预计2029年将达到404亿美元

无线音频&#xff0c;是指将音频型号以无线电波作为载体&#xff0c;从一个设备传输到另外一个设备&#xff0c;实现音频的无线传输。 最常见的是蓝牙传输&#xff0c;传输频率2.4G&#xff0c;蓝牙音箱、蓝牙耳机都属于蓝牙音频传输&#xff0c;蓝牙音频传输是双向传输&#x…

主板电路学习; 华硕ASUS K43SD笔记本安装win7X64(ventoy)

记录 老爷机 白色 华硕 K43SD 笔记本 安装 win7X64 1. MBR样式常规安装win7X64Sp1 (华硕 K43SD 安装 win7X64 ) 老爷机 白色 华硕 K43SD 笔记本 安装 win7X64 &#xff08;常规安装&#xff09; 设置&#xff1a; 禁用UEFI 启用AHCI ventoy制作MBR&#xff08;非UEFI&#…

性能优化-OpenCL kernel 开发

「发表于知乎专栏《移动端算法优化》」 本文主要介绍OpenCL的 Kernel&#xff0c;包括代码的实例以及使用注意的详解。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;高性能&#xff08;HPC&#xff09;开发基础教…

光的干涉与衍射

引用内容来自曹天元的《上帝掷骰子吗&#xff1f;&#xff1a;量子物理史话》&#xff0c;其余内容来自课程。 牛顿光的色散实验 色散实验是牛顿所做的有名的实验之一。实验的情景在一些科普读物里被渲染得令人印象深刻&#xff1a;炎热难忍的夏天&#xff0c;牛顿却戴着厚重的…

谁懂啊,金蝶BI财务分析居然这么简单

接触过财务数据分析的&#xff0c;都知道财务分析中指标计算复杂&#xff0c;维度、指标组合多变&#xff0c;而每当出现了一处变化&#xff0c;就得全部推动重来&#xff0c;那工作量和复杂程度让人头皮发麻。就算是金蝶系统&#xff0c;也是偏流程&#xff0c;对财务数据分析…

OpenGPTs:一款外挂般的GPTs管理器,由ChatPaper团队开源!

OpenGPTs-非常好用的开源GPTs管理器. 一句话介绍 非常好用的GPTs管理器&#xff0c;ChatPaper团队开源一款功能强大的浏览器插件&#xff0c;适合所有拥有Plus权限的朋友。 为什么要做OpenGPTs&#xff1f; &#x1f914;&#x1f4a1; 众所周知&#xff0c;OpenAI官网的GPT…

浅谈 ST 表

更好的阅读体验 浅谈 ST 表 这种东西还是很简单的&#xff0c;但是涉及左移右移&#xff0c;模板容易打挂&#xff0c;写篇笔记。 ST 表是什么 虽然这个是通过二维数组来实现的&#xff0c;但是我不是很喜欢称之为“表”。我觉得完全可以看作是在一维序列上的区间&#xff…

sqli-labs通关笔记(less-11 ~ less16)

上一篇文章说了sqli-labs的less-1到less-10的注入方法&#xff0c;这一篇从less-11开始。 由于从11关开始都是post请求&#xff0c;不会像前十关一样存在符号转成unicode的麻烦&#xff0c;所以不再使用apifox&#xff0c;直接从页面上进行测试。 Less-11 老规矩&#xff0c;…

【深度学习】CodeFormer训练过程,如何训练人脸修复模型CodeFormer

文章目录 BasicSR介绍环境数据阶段 I - VQGAN阶段 II - CodeFormer (w0)阶段 III - CodeFormer (w1) 代码地址&#xff1a;https://github.com/sczhou/CodeFormer/releases/tag/v0.1.0 论文的一些简略介绍&#xff1a; https://qq742971636.blog.csdn.net/article/details/134…

React Hooks 源码解析:useEffect

React Hooks 源码解析&#xff08;4&#xff09;&#xff1a;useEffect React 源码版本: v16.11.0源码注释笔记&#xff1a;airingursb/react 1. useEffect 简介 1.1 为什么要有 useEffect 我们在前文中说到 React Hooks 使得 Functional Component 拥有 Class Component 的…

206.反转链表(附带源码)

一、思路 二、代码 一、思路 将指针调转一个方向就行&#xff0c;很简单 做法&#xff1a; 定义2个指针&#xff1a;prev、 cur、 next 当next为空时&#xff0c;循环结束 思路清晰&#xff0c;操作清楚&#xff0c;开始敲代码。 二、代码 struct ListNode* reverseList(s…

Tide Quencher 8WS-Mal,TQ8WS-Mal,能够针对特定的荧光物质进行淬灭

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;Tide Quencher 8WS maleimide&#xff0c;TQ8WS maleimide &#xff0c;Tide Quencher 8WS Mal&#xff0c;TQ8WS Mal&#xff0c;荧光淬灭剂Tide Quencher 8WS 马来酰亚胺 &#xff0c;TQ8WS 马来酰亚胺 一、基本信…

【蓝桥杯备赛Java组】语言基础|竞赛常用库函数|输入输出|String的使用|常见的数学方法|大小写转换

&#x1f3a5; 个人主页&#xff1a;深鱼~&#x1f525;收录专栏&#xff1a;蓝桥杯&#x1f304;欢迎 &#x1f44d;点赞✍评论⭐收藏 目录 一、编程基础 1.1 Java类的创建 1.2 Java方法 1.3 输入输出 1.4 String的使用 二、竞赛常用库函数 1.常见的数学方法 2.大小写转…

链表的分类

链表的八种类别: 这三行属性结合,共有八种链表: 1.带头单向循环 2.带头双向循环 3.带头单向不循环 4.带头双向不循环 5.带头单向循环 6.带头双向循环 7.带头单向不循环 8.带头双向不循环 一.单向或双向 单向链表只有一个指向后续节点的指针 双向链表则有两个指针,分别…

高客单价企业必读:私域运营趋势分析与实操技巧

一、深入挖掘&#xff1a;场景洞察的新维度 当我们收到销售的群发信息时&#xff0c;通常会感到被打扰或骚扰&#xff0c;这是因为这些信息通常是基于广泛的受众群体发送的&#xff0c;缺乏针对个体消费者的定制化和个性化。这种缺乏个性化的沟通方式很容易被消费者视为不必要…

ITSS认证有用吗❓属于gj级证书吗❓

&#x1f525;ITSS由中国电子技术标准化研究院推出&#xff0c;包括“IT 服务工程师”和“IT 服务经理”两种认证。该系列认证符合GB/T 28827.1 的评估和ITSS服务资质升级要求。 &#x1f3af;ITSS是受到gj认可的&#xff0c;在全国范围内对IT服务管理人员从业资格为一的权威的…