JVM详解(包括JVM内存模型与GC垃圾回收)

📖前言:

        学会使用Java对于一个程序员是远远不够的。Java语法的掌握只是一部分,另一部分就是需要掌握Java内部的工作原理,从编译到运行,到底是谁在帮我们完成工作的?

        接下来着重对Java虚拟机,也就是JVM有一个深刻认识,对日后完成项目的开发或是更底层的开发有很大的帮助。

        接下来说的均为个人的一点小见解和观点,希望大家多多指点!

🎈JVM:

        JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。

虚拟机是指通过软件模拟的具有完整硬件功能的、运⾏在⼀个完全隔离的环境中的完整计算机系统。

常⻅的虚拟机:JVM、VMwave、Virtual Box。

JVM 和其他两个虚拟机的区别:
1 .  VMwave与VirtualBox是通过软件模拟物理CPU的指令集,物理系统中会有很多的寄存器;
2.JVM则是通过软件模拟Java字节码的指令集,JVM中只是主要保留了PC寄存器,其他的寄存器都进⾏了裁剪。
JVM 是⼀台被定制过的现实当中不存在的计算机。

🎨JVM与JDK的关系?

        知道JVM的基础概念,可能现在就有点懵了,JVM和JDK有什么关系吗?那么开始梳理一下与JAVA开发相关的组成部分;

✨JDK:

        官方JDK(Java Development Kit) 是Java开发工具包,包含了Java编译器(javac)、Java程序打包工具(jar)、Java程序运行环境(JRE)、文档生成工具(javadoc)以及其他开发工具,如调试的工具(jdb)。JDK是为Java开发人员提供的完整开发环境,包含了开发和运行Java程序所需的一切。

         非官方:JDK就是一个工具包,JDK是JRE的超集,JDK包含了JRE的所有开发,调试和监视应用程序等工具。当要开发Java应用程序时,需要安装JDK.

(JDK里面的工具非常多,是这么多工具才能支撑起我们编写Java程序)

        当然有一个重要的组成部分——JRE(Java程序运行环境).

接下来就针对JRE做一个详细说明:

✨JRE:

        官方JRE(Java Runtime Environment) 是Java运行环境,包含了JVM和Java类库。JRE是运行Java程序所需的环境,它提供了Java程序运行所需的库文件和JVM。因此,如果你只需要运行Java程序,那么只需要安装JRE即可。        

        

需要区分的地方:

        这里再穿插一下IDEA是什么,IDEA是编写代码的平台,里面集成了一些好用的工具,例如预编译工具,能够在出现一些语法错误的时候提示我们,但是起到编译运行的还是JVM虚拟机!

⚽JVM内存模型:        

        首先在开头处需要声明一下: JVM内存模型与JMM内存模型不是一回事,JVM内存模型就是虚拟机内部的内存模型,但是JMM内存模型主是描述Java线程之间如如何工作的,如何做到线程之间共享变量的。

        JVM内存模型分为5个区,由这5个区合力搭建出JVM内存模型的。

程序计数器:记录了要执行的下一条指令的地址

栈:

        虚拟机栈:保存临时变量、参数、函数调用的关系

        本地方法栈:与虚拟机栈类似、底层是C或C++代码

堆:保存了new的对象

方法区(元数据区):保存了静态变量、常量、常量池等

        栈区、程序计数器是线程私有的

        堆区、方法区是线程共享的 

🏉类加载过程:

        了解了JVM内存模型,接下来需要了解.class文件在JVM读取与加载的过程。

        1.加载:读取.class文件中的内容

        2.验证:校验读取到的内容是否符合JVM规范。

        3.准备:为类的静态变量分配内存,并将其初始化为默认值。

        4.解析:将符号引用全部替换为直接引用

        5.初始化:此阶段是执行类构造器()方法的过程。此方法由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并而成。当初始化一个类的时候,如果发现其父类还未进行初始化,则需要先触发其父类的初始化。Java虚拟机会保证一个类的()方法在多线程下被同步加锁。

⚾双亲委派模型:

        在类加载时,需要遵循双亲委派模型:

        如果一个类被请求加载时,首先不会自己加载,将加载的请求抛给父类,如果父类可以加载,自己就不再加载,如果父类不能加载,自己再进行加载。

优先级由高到低:标准库类加载器->扩展库类加载器->第三方库类加载器->自定义类加载器

        如下图:

双亲委派模型作用:       

1. 避免重复加载类: ⽐如 A 类和 B 类都有⼀个⽗类 C 类,那么当 A 启动时就会将 C 类加载起来,那么在 B 类进⾏加载时就不需要在重复加载 C 类了。
2. 安全性 :使⽤双亲委派模型也可以保证了 Java 的核⼼ API 不被篡改,如果没有使⽤双亲委派模型,⽽是每个类加载器加载⾃⼰的话就会出现⼀些问题,⽐如我们编写⼀个称为 java.lang.Object类的话,那么程序运⾏的时候,系统就会出现多个不同的 Object 类,⽽有些 Object 类⼜是用户自己提供的因此安全性就不能得到保证了。

🥎类初始化顺序(带有继承关系):

        父类静态代码块、静态变量->子类静态代码块、静态变量->父类普通变量->父类构造函数->子类普通方法->子类构造方法

🏀GC垃圾回收:

        首先需要搞清楚,哪里的垃圾需要回收,那里的垃圾不需要回收?        

        线程私有的区域中的垃圾我们不需要回收,当线程结束时,这些区域也会跟着清空

        线程共享的区域,如果线程结束,但是线程共享区中的引用对象不会随之消失。

        因此着重关注的是两个区域——堆区、方法区

        但是相较于创建的量和空间的消耗来说,堆区是垃圾回收的重灾区,但是方法区也有垃圾回收机制,但是不怎么关注。

🏐如何判断该对象是否是垃圾?

        如何判定堆区中的对象就是垃圾呢?有以下几种方法:

🍿1.引用计数法:

        采用计数的方式,如何一个对象被引用,此时计数器+1,如何不在引用该对象计数器的值就-1。

造成的问题:

        如果采用方法进行垃圾的判定,会造成"循环引用"的问题,例如:

class Student{private String name;public Student student;public Student(String name) {name = this.name;}
}
public class Test {public void circulation(){Student a = new Student("a");Student b = new Student("b");a.student = b;b.student = a;a = null;b = null;}
}

此时明明a、b两个引用已经断开指向a、b的对象,但是其内部还有相互的指向,没有办法被释放了。

🍕2.可达性分析:

        为了解决上述出现的问题,可以定期进行扫描,如果发现虽然被引用着,但是到达不了GCroots也会被视为垃圾,如下图:

                     

         也就是从GC Roots开始扫描,如果是能到达的对象此时构成了引用链,如果在某个对象在经过下次扫描不在这条引用链上了,就被视为"垃圾"。

   该方法被作为GC垃圾回收的首选方法。但是在这个过程中可能会造成STW(Stop The World),可以理解为时间停顿。

🥯垃圾回收方法:

        通过可达性分析以后判断出哪些对象是垃圾,接下来就来谈一谈这些垃圾是如何被回收的?

有以下方法:

🌭 1.标记回收:

        经过可达性分析以后,如果是垃圾,此时被标记一下。之后经过多轮检测之后,将标记的垃圾进行清除:

        

缺点:

        造成内存碎片化问题,此时在存储效率上会大减折扣。

🧇2.标记整理:

        在标记回收算法的基础上,进行改良,因为上述的做法会造成内存碎片问题,如果每次回收以后,对内存中存活的对象继续宁整理,整理在一起,此时内存空间可利用率会提高。

        

缺点:

        整理复制需要消耗大量的实践,时间效率降低。

🧈3.复制算法:

        如果我么每次将内存空间分为两部分,一部分空出来,另一部分使用,垃圾回收只需要对使用的一部分进行回收,进行标记,经过多轮之后,将存活的对象复制到另一块没有使用的内存当中。

 

缺点:

        如果存活的对象较多,此时复制时比较消耗时间。

🍞4.分代回收算法:

        将堆区中的区域划分为新生代与老年代

 

新生代又被划分为:伊甸区、幸存区

  • 堆内存为两个区:新生代 (Young) 和老年代 (Old);
  • 新生代默认占堆内存的 1/3,老年代默认占堆内存的 2/3;
  • 新生代又分为 Eden 区、Survivor From区、Survivor To区默认比例是 8:1:1   

过程:

        首次被创建的对象先进入伊甸区,之后经过可达性分析与复制算法,将幸存的对象放入幸存区,再次经多轮过可达性分析与复制算法,此时将最终存活的对象放入老年代。老年代中进行可达性分析的频次就比较低了。

😶常见的GC垃圾回收器:

        上述讲的都是一些垃圾回收的一些思路,这些GC垃圾回收器内部回收垃圾时都有用到上述的思路。

1️⃣1.GMS垃圾收集器:

        老年代收集器,并发GC,GMS是一种获取最短停顿时间(STW)为目标的收集器。

实现原理:

        其内部是基于标记-清除算法实现的。(具体大家可以自行了解)

由于整个过程中耗时最⻓的并发标记和并发清除过程收集器线程都可以与⽤⼾线程⼀起⼯作,所以,从总体上来说,CMS收集器的内存回收过程是与⽤⼾线程⼀起并发执⾏的。       

2️⃣2.G1垃圾收集器 :

        全区域的垃圾收集器,其主要的做法是将分代回收算法中的区域划分为更小的区域块,此时不再是一次性进行复制算法回收,只对一部分进行可达性分析+复制算法回收。

年轻代垃圾收集:
        在G1垃圾收集器中,年轻代的垃圾回收过程使⽤复制算法。把Eden区和Survivor区的对象复制到新的Survivor区域。
老年代垃收集:
对于⽼年代上的垃圾收集,G1垃圾收集器也分为4个阶段,基本跟CMS垃圾收集器⼀样,但略有不同:
初始标记 (Initial Mark)阶段 - G1需要暂停应⽤程序的执⾏,它会标记从根对象出发,在根对象的第⼀层孩⼦节点中标记所有可达的对象。但是G1的垃圾收集器的Initial Mark阶段是跟minor gc⼀同发⽣的。也就是说,在G1中,你不⽤像在CMS那样,单独暂停应⽤程序的执⾏来运⾏Initial Mark阶段,而是在G1触发minor gc的时候⼀并将年⽼代上的Initial Mark给做了。
并发标记 (Concurrent Mark)阶段 - 在这个阶段G1做的事情跟CMS⼀样。但G1同时还多做了⼀件事 情,就是如果在Concurrent Mark阶段中,发现哪些Tenured region中对象的存活率很⼩或者基本没有对象存活,那么G1就会在这个阶段将其回收掉,⽽不⽤等到后⾯的clean up阶段。这也是Garbage First名字的由来。同时,在该阶段,G1会计算每个 region的对象存活率,⽅便后⾯的clean up阶段使⽤ 。
最终标记 (CMS中的Remark阶段) - 在这个阶段G1做的事情跟CMS⼀样, 但是采⽤的算法不同,G1采⽤⼀种叫做SATB(snapshot-at-the-begining)的算法能够在Remark阶段更快的标记可达对象。
筛选回收( Clean up/Copy)阶段 - 在G1中,没有CMS中对应的Sweep阶段。相反 它有⼀个Cleanup/Copy阶段,在这个阶段中,G1会挑选出那些对象存活率低的region进⾏回收,这个阶段也是和minor gc⼀同发⽣的。

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

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

相关文章

【无标题】大亚湾文化体育场多美啊。

请推荐一些常用并且免费的,可直接在线运行【Python】代码的平台并列出对应网址 好的,用户想让我推荐一些常用且免费的、可以直接在线运行Python代码的平台,并且需要列出对应的网址。我需要先回想一下自己知道的在线Python运行环境&#xff0…

权限提升—Windows权限提升土豆家族溢出漏洞通杀全系

前言 OK,Java安全更新不下去了,实在是太难啦啊,想起来提权这一块没怎么更新过,接下来都主要是更新提权这一块的文章了,Java安全的话以后有耐心再搞了。 手动提权 今天主要是讲这个手动的提权,手动提权相…

Vue3 知识点总结

Vue3 知识点总结 1. 核心概念 1.1 Composition API 1.1.1 setup 函数 setup是Vue3中的新的配置项,是组件内使用Composition API的入口在setup中定义的变量和方法需要return才能在模板中使用setup执行时机在beforeCreate之前,this不可用 export defa…

python --face_recognition(人脸识别,检测,特征提取,绘制鼻子,眼睛,嘴巴,眉毛)/活体检测

dlib 安装方法 之前博文 https://blog.csdn.net/weixin_44634704/article/details/141332644 环境: python3.8 opencv-python4.11.0.86 face_recognition1.3.0 dlib19.24.6人脸检测 import cv2 import face_recognition# 读取人脸图片 img cv2.imread(r"C:\Users\123\…

【bug】[42000][1067] Invalid default value for ‘xxx_time‘

MySQL错误解决:Invalid default value for xxx_time’问题分析与修复方案 问题描述 在MySQL数据库操作中,当尝试创建或修改表结构时,可能会遇到以下错误信息: [bug] [42000][1067] Invalid default value for xxx_time这个错误…

Go环境相关理解

Linux上安装的环境变量 ## set go env export GOPATH$HOME/go_workspace export GOPATH/usr/local/go export PATH$PATH:$GOPATH/bin go.mod 和go.sum的理解 go.mod文件 ‌go.mod文件定义了模块的路径和依赖版本‌。它遵循 语义化版本2.0.0规范,记录了当前项目所依…

Next.js 深度解析:全栈React框架的架构哲学与实践精髓

Next.js 作为 React 生态中最流行的全栈框架,已经超越了简单的SSR工具,发展成为完整的Web开发解决方案。以下从八个维度进行深度剖析: 一、核心架构设计 双引擎驱动模型 页面路由系统:基于文件系统的约定式路由渲染引擎&#xff…

禾赛盈利了,但激光雷达没有胜利

还远没有到激光雷达党欢呼的时候。 3月,随着禾赛科技公布2024年报,全世界第一家也是唯一一家实现全年盈利的激光雷达上市公司诞生,为了这个盈利目标,禾赛科技奋斗了十年。 但极大的出货量和不高的盈利水平,让禾赛科技…

心房颤动新机制:ATM/p53通路早期抑制

急性心肌梗死(AMI)是心血管疾病中的“大魔头”,它悄无声息地侵蚀着心脏的肌肉,导致心脏功能受损,严重时甚至危及生命。而心房颤动(AF),这一常见的心律失常,往往在AMI后悄…

Linux 安装 Redis

虚拟机安装 linux https://www.bilibili.com/video/BVldD42177qg?p16 1、安装 gcc,编译环境 yum y install gcc-g 2、将 redis-7.2.4.tar.gz放到 linux。如,放到 opt 里 3、进入/opt 目录下,解压 tar -zxvf redis-7.2.4.tar.gz 4、进入 redis-7.2.4.tar…

六级备考 词汇量积累(day11)

sculpture 雕像 allege 指责,声称 pledge 发誓 breach 违背,违反 defaulty 违约,违反 infringe 侵犯 infringing on small farmers interest blacmail 勒索 idle 无所事事的 deceive 欺骗 perceive 察觉 conceive 设想 conception 设想 verdi…

关于金碟K3,禁用和启用需要流程审批后执行

真是难受,是设计师蠢呢自己问题比较多呢,现在都还没有弄好 点击禁用和启用,通过流程来执行 到底是蠢呢还是设计问题,搞了半日没有效果,搞那么复杂! 而且有样板都没有草鞋成功 BOS设计,表单属性,操作列表: 1、启用禁用流程

导入 Excel 规则批量修改或删除 PDF 文档内容

需要对 PDF 文档内容进行修改的时候,通常我们会需要借助一些专业的工具来帮我们完成。那我们如果需要修改的 PDF 文档较多的时候,有什么方法可以帮我们实现批量操作呢?今天这篇文章就给大家介绍一下当我们需要批量修改多个 PDF 文档的时候&am…

msyql--基本操作之运维篇

检查 root 用户的权限 查看该用户针对这个数据库的权限 -- 如果在终端连接mysql时需要 mysql -u root -p -- 查看用户权限 SELECT user, host FROM mysql.user WHERE user root;可以看的出来root有他的访问权限,如过没有localhost或者% 说明没有访问权限 添加…

Vue 3使用 Socket

在 Vue 3 中使用 Socket(如 WebSocket 或基于 WebSocket 的库比如 Socket.IO)可以通过组合式 API(Composition API)来实现得更清晰、模块化。下面我给你展示一个完整的例子,包括使用原生 WebSocket 和使用 Socket.IO 的…

云计算:探索现代科技的未来之云

文章目录 云计算基本概念云计算是什么注意 云计算的价值云计算的部署模式云计算的服务模式主流的云计算技术AWS简介AWS建立了广阔的合作伙伴生态 VMware简介VMware服务介绍 华为云简介华为云Stack模式 云计算基本概念 云计算是什么 云计算是一种模型,它可以实现随时…

光学像差的类型与消除方法

### **光学像差的类型、理解与消除方法** 光学像差是指实际光学系统成像时,由于透镜或反射镜的非理想特性导致的光线偏离理想路径,从而影响成像质量的现象。像差可分为**单色像差**(与波长无关)和**色差**(与波长相关…

什么是ecovadis验厂?ecovadis验厂的好处?ecovadis验厂的重要意义

1. 什么是EcoVadis验厂? EcoVadis验厂(又称EcoVadis评估)是国际权威的 企业社会责任(CSR)和可持续发展(ESG)在线评估,通过审核企业在 环境、劳工与人权、商业道德、可持续采购 四大…

STM32蜂鸣器播放音乐

STM32蜂鸣器播放音乐 STM32蜂鸣器播放音乐 Do, Re, Mi, Fa, 1. 功能概述 本系统基于STM32F7系列微控制器,实现了以下功能: 通过7个按键控制蜂鸣器发声,按键对应不同的音符。每个按键对应一个音符(Do, Re, Mi, Fa, Sol, La, Si&a…

基于 OCO - 2 氧气 A 带辐射数据与地面台站气压观测数据构建近地面气压监测算法方案

基于 OCO - 2 氧气 A 带辐射数据与地面台站气压观测数据构建近地面气压监测算法方案 一、数据获取与准备 (一)OCO - 2 氧气 A 带辐射数据 数据下载:从 OCO - 2 官方数据发布平台(如 NASA 的相关数据存储库),按照研究所需的时间范围(例如,近 5 年的数据以获取足够的样本…