深入理解 JVM(重点:双亲委派模型 + 垃圾回收算法)

一、什么是 JVM?

JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。可以认为 JVM 是一台被定制过的现实当中不存在的计算机,Java程序最终是在JVM(Java虚拟机)中运行的。

二、JVM 的执行流程

三、JVM 运行时数据区

  1. 堆(Heap):是Java程序中最大的一块内存区域,用于存储使用new关键字创建的对象实例和数组对象。

  2. 栈(Stack):为每个线程分配单独的栈空间,主要用于存储方法调用时的栈帧、局部变量等。

  3. 方法区(Method Area):主要用于存储类的结构信息(类对象)、方法元信息、常量池、静态变量等。

  4. 程序计数器(Program Counter Register):每个线程都有一个独立的程序计数器,用于存储当前线程正在执行的指令地址或下一条即将执行的指令地址。

四、JVM 类加载机制

1、类加载过程

程序要想运行,就要把依赖的“指令和数据”加载到内存中,这里主要体现为将 .class 文件加载到内存中的过程。总结为5个词就是:

  1. 加载:它通过类加载器(ClassLoader)查找并读取类的字节码文件,将其加载到内存中。加载过程中会生成一个代表该类的Class对象,用于后续操作。
  2. 验证.class文件具有明确的数据格式
  3. 准备:正式为类中定义的变量(即静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段。
  4. 解析:是 Java 虚拟机将常量池内的符号引用替换为直接引用的过程,也就是初始化常量的过程。
  5. 初始化:主要初始化静态成员、执行静态代码块、加载父类(如果存在父类)等过程。

2、双亲委派模型

在 “加载” 这个过程中涉及到类加载器的概念,JVM 中内置了三个类加载器,构成“双亲委派模型:

  1. BootStrap ClassLoader:负责加载 Java 标准库中的类
  2. Extension ClassLoader:负责加载 Sun、Oracle拓展库的类
  3. Application ClassLoader:负责加载项目中自定义类以及第三方库中的类

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最 终都应该传送到最顶层的类加载器中,只有当父加载器反馈自己无 法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。直到在某一层加载完成进入下一环节,如果始终没有找到,则抛出异常:ClassNotFoundException

五、JVM 垃圾回收策略

JVM垃圾回收(Garbage Collection)主要用于回收不再被程序引用的内存对象。而对象又是存储在堆内存上的,因此CG的主要目标就是 ,并且 CG 是以 对象 为单位进行释放的。至于其他内存区域:

:方法调用完毕,方法的栈帧、局部变量就随着出栈操作销毁了。整个栈也是随着线程一起销毁。

方法区:主要存储类对象,很少涉及“卸载”操作。

程序计数器:只是是一个单纯的地址整数,随着线程一起销毁。

1、死亡对象的判断算法

Java堆中存放着所有的对象实例,垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象哪些还存活,哪些已经"死去"。判断对象是否已"死"有主要有如下 2 种算法:

(1)引用计数算法

给对象增加一个引用计数器,每当有一个地方引用它时,计数器就+1;当引用失效时,计数器就-1;任何时刻计数器为0的对象就是不能再被使用的,即对象已"死"。

使用引用计数法判断对象存活的思想很简单,一般情况下判定效率也比较高,但是 引用计数法无法解决对象的循环引用问题。

(2)可达性分析法(Java 采取的方案)

把对象中的引用关系理解为一个树形结构,通过一系列称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,只要能遍历到的对象都是可达的,否则证明此对象是不可用的。

这里的GC Roots包含以下几种:

  1. 栈上引用的对象
  2. 方法区中常量池中引用的对象
  3. 方法区中静态成员引用的对象

虽然可达性分析解决了引用计数法中的 循环引用 问题,但是搜索的过程可能会消耗更多的时间,并且为了防止在搜索的过程中引用关系发生变化,会让一些业务线程暂停工作,也就是产生STW(Stop-The-World)问题。

2、垃圾回收算法

(1)标记清除

"标记-清除"算法是最基础的垃圾回收算法。算法分为"标记"和"清除"两个阶段 : 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

标记清除算法最大的问题是会产生 内存碎片。一般在申请内存时,往往是申请整块连续的空间,而内存碎片会导致空间利用率大打折扣。

(2)复制算法

它将整个可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后再把已经使用过的内存区域一次清理掉。这样做的好处是每次都是对整个半区进行内存回收,内存分配时也就不需要考虑内存碎片等复杂情况。

这种算法的缺陷是内存空间的利用率比较低,将最大可用空间减为原来的一般。并且如果可用内存中垃圾很少,需要保留的对象很多,此时复制成本就比较高,效率就会变低。

(3)标记整理

标记整理也可以解决内存碎片的问题,总体思路类似于顺序表删除中间元素,每次将存活对象都向一端移动,然后直接清理掉端边界以外的内存。

标记整理算法,由于每次需要挪动,因此导致效率降低。

(4)分代回收(JVM 采用)

分代算法是通过区域划分,实现不同区域(阶段)采用不同的垃圾回收策略。大量的经验表明,Java对象大多都具备朝 生夕灭的特性,一般经过一轮扫描就有大量新生代对象死去,如果一个对象存活的时间很长了,那么经验表明他将会持续存活更长的时间。

  1. 新建的对象,会放到伊甸区。当垃圾回收扫描到伊甸区后,绝大部分对象会在第一轮 GC 中被干掉。
  2. 如果伊甸区的对象熬过第一轮 GC,会通过复制算法,将存活的对象拷贝到生存区。
  3. 生存区分为两部分,大小相等,一次使用一半,垃圾回收扫描到生存区,发现垃圾,就使用复制算法,将仍然存活的对象复制到生存区的另一半。
  4. 当生存区的对象熬过若干轮 GC 后,认为年龄增长到一定程度,则进入老年区,会通过复制算法将其拷贝到老年代。
  5. 进入老年代的对象,一般都是存活时间较长的对象,死亡的概率就比新生代中小了很多,因此针对老年代的 GC 频率就会降低很多。如果某次扫描发现老年代中某个对象是垃圾,则直接使用标记整理的方式删除。
  6. 特殊情况:如果某个对象非常大,则直接进入老年代。因为大对象进行复制算法成本比较高,并且大对象不会有很多。

六、Java 虚拟机中的垃圾收集器(了解)

Java虚拟机中的三个垃圾收集器是基于以上算法的具体实现,通常会基于以上做出一些改进和优化。这里主要列举了两个:

  1. CMS(Concurrent Mark-Sweep)垃圾收集器:CMS是一种旨在减少应用程序停顿时间的垃圾收集器。它采用并发标记-清除算法,允许在大部分清除过程中应用程序继续运行。
  1. G1(Garbage-First)垃圾收集器:G1是一种面向服务端应用程序的垃圾收集器,旨在提供可控制的停顿时间和高吞吐量。它使用分代、区域化的垃圾回收策略,可以更精确地控制停顿时间。

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

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

相关文章

Android---Android 是如何通过 Activity 进行交互的

相信对于 Android 工程师来说,startActivity 就像初恋一般。要求低,见效快,是每一个菜鸟 Android 工程师迈向高级 Android 工程师的必经阶段。经过这么多年的发展,startActivity 在 google 的调教下已经变得愈发成熟,对…

【Express】服务端渲染(模板引擎 EJS)

EJS(Embedded JavaScript)是一款流行的模板引擎,可以用于在Express中创建动态的HTML页面。它允许在HTML模板中嵌入JavaScript代码,并且能够生成基于数据的动态内容。 下面是一个详细的讲解和示例,演示如何在Express中…

使用jsqlparser创建MySQL建表语句

语法 create table [IF NOT EXISTS] 表名 ( 字段名 类型 [约束条件], 字段名 类型 [约束条件], 字段名 类型 [约束条件], 字段名 类型 [约束条件] ); 字段定义在括号内约束条件可以有多个多个字段定义之间用都会隔开 常见约束 NOT NULL 非空DEFAULT 0 默认值AUTO_INCREMENT…

Mac安装Kali保姆级教程

Mac安装Kali保姆级教程 其他安装教程:使用VMware安装系统Window、Linux(kali)、Mac操作系统 1 虚拟机安装VM Fusion 去官网下载VM Fusion 地址:https://customerconnect.vmware.com/en/evalcenter?pfusion-player-personal-13 …

网工记背配置命令(3)----POE配置示例

POE 供电就是通过以太网供电,这种方式仅凭借那根连接通信终端的网线就可完成为它们供电。POE提供的是-53V~0v 的直流电,供电距离最长可达 100m。PoE 款型的交换机的软件大包天然支持 POE,无需 license,通过执行 poe-enable 命令使…

Android 10.0 禁止弹出系统simlock的锁卡弹窗功能实现

1.前言 在10.0的系统开发中,在一款产品中,需要实现simlock锁卡功能,在系统实现锁卡功能以后,在开机的过程中,或者是在插入sim卡 后,当系统检测到是禁用的sim卡后,就会弹出simlock锁卡弹窗,要求输入puk 解锁密码,功能需求禁用这个弹窗,所以就需要看是 哪里弹的,禁用…

71.同步使用你的可组合代码

你应该始终在setup()钩子或<script setup>中同步调用你的composables。调用composables时&#xff0c;最好不要使用await或Promise.all()。例如&#xff0c;以下使用setup()钩子的代码是不推荐的&#xff1a; <script> import { ref, watch, onMounted, onUnmounte…

机器学习-迁移学习

分类 按照特征分类 当源域和目标域含有一些共同的交叉特征时&#xff0c;我们可以通过特征变换&#xff0c;将源域和目标域的特征变换到相同空间&#xff0c;使得该空间中源域数据与目标域数据具有相同分布的数据分布&#xff0c;然后进行传统的机器学习。基于模型的迁移&#…

记一次生产大对象及GC时长优化经验

最近在做一次系统整体优化,发现系统存在GC时长过长及JVM内存溢出的问题,记录一下优化的过程 面试的时候我们都被问过如何处理生产问题&#xff0c;尤其是线上oom或者GC调优的问题更是必问&#xff0c;所以到底应该如何发现解决这些问题呢&#xff0c;用真实的场景实操&#xff…

前端工程化知识系列(1)

目录 1. 什么是前端工程化&#xff0c;以及它为前端开发带来了哪些好处&#xff1f;2. 你使用过哪些版本控制系统&#xff1f;描述一下你在团队中如何处理代码合并和冲突解决的经验。3. 什么是Git&#xff0c;它的工作原理是什么&#xff1f;可以解释一下常用的Git命令吗&#…

计算机毕业设计 基于协同过滤算法的白酒销售系统的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

Apache Log4j Server (CVE-2017-5645) 反序列化命令执行漏洞

文章目录 Apache Log4j Server 反序列化命令执行漏洞&#xff08;CVE-2017-5645&#xff09;1.1 漏洞描述1.2 漏洞复现1.2.1 环境启动1.2.2 漏洞验证1.2.3 漏洞利用 1.3 加固建议 Apache Log4j Server 反序列化命令执行漏洞&#xff08;CVE-2017-5645&#xff09; 1.1 漏洞描述…

【大数据】Hive SQL语言(学习笔记)

一、DDL数据定义语言 1、建库 1&#xff09;数据库结构 默认的数据库叫做default&#xff0c;存储于HDFS的&#xff1a;/user/hive/warehouse 用户自己创建的数据库存储位置&#xff1a;/user/hive/warehouse/database_name.db 2&#xff09;创建数据库 create (database|…

allegro中shape的一些基本操作(一)——添加和修改shape

添加shape 简单添加shape的方式有3种&#xff0c;如下图所示 点击选择相应的shape模式后可以在option面板中设置相应的shape参数&#xff08;这里不做过多介绍&#xff0c;里面可以设置shape的大小、静态或动态shape等参数&#xff09;&#xff0c;然后再用鼠标在相应的层上添…

计算机网络 | 网络层

计算机网络 | 网络层 计算机网络 | 网络层功能概述SDN&#xff08;Software-Defined Networking&#xff09;路由算法IPv4IPv4 分组IPv4 分组的格式IPv4 数据报分片 IPv4 地址与 NATIPv4 地址网络地址转换&#xff08;NAT&#xff09; 子网划分和子网掩码子网划分子网掩码 无分…

Hadoop3教程(十二):MapReduce中Shuffle机制的概述

文章目录 &#xff08;95&#xff09; Shuffle机制什么是shuffle&#xff1f;Map阶段Reduce阶段 参考文献 &#xff08;95&#xff09; Shuffle机制 面试的重点 什么是shuffle&#xff1f; Map方法之后&#xff0c;Reduce方法之前的这段数据处理过程&#xff0c;就叫做shuff…

java double 保留两位小数

在Java中&#xff0c;你可以使用 DecimalFormat 或 String.format 来保留 double 类型的数字两位小数。以下是两个例子&#xff1a; 使用 DecimalFormat import java.text.DecimalFormat;public class Main {public static void main(String[] args) {double number 123.456…

【opencv】windows10下opencv4.8.0-cuda Python版本源码编译教程

【opencv】windows10下opencv4.8.0-cuda Python版本源码编译教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【opencv】windows10下opencv4.8.0-cuda Python版本源码编译教程前言准备工具anaconda/cuda/cudnnanaconda创建环境(选做)安装原…

Opencv——颜色模型+通道分离与合并

视频加载/摄像头调用 VideoCapture允许一开始定义一个空的对象 VideoCapture video VideoCapture(const String &filename,int apiPreferenceCAP_ANY) filename:读取的视频文件或者图像序列名称 apiPreference:读取数据时设置的属性&#xff0c;例如编码格式、是否调用Op…

阿里SQL规约

阿里SQL规约 集团重点强制SQL规约如下&#xff1a; 1、【强制】不要使用count(列名)或count(常量)来替代count()&#xff0c;count()就是SQL92定义的标准统计行数的语法&#xff0c;跟数据库无关&#xff0c;跟NULL和非NULL无关。 2、【强制】count(distinct col) 计算该列除…