JVM基础知识

一、JVM的内存区域划分

一个进程在运行的时候,会向操作系统申请到内存资源,从来存放程序运行的相关数据。

JVM本质上就是一个java进程,在运行的时候也会从操作系统那搞一块内存,供Java代码执行使用。

JVM又把申请的一块内存根据不同的用途划分出了不同区域。

每一个线程中都独有一份自己的栈空间和程序计数器(PC)

栈:存放方法调用关系,局部变量。

程序计数器(PC):记录当前线程执行的下一条指令的内存地址。

堆:存放对象的实例,即new出来的对象都在这里。

方法区(元数据区):存放类对象,常量池,静态成员。

二、JVM类加载机制

类加载本质上就是将.class文件(硬盘)加载到内存(方法区)中。

Java程序最开始在编写的时候是一个.java文件,然后通过编译生成.class(字节码)文件,运行java程序,JVM就会读取.class文件,把文件的内容放到内存中,构造.class对象。

类加载的过程

  • 加载:找到.class文件,打开文件,读取文件内容。

  • 验证:检查当前.class文件的格式。

  • 准备:给类对象分配内存空间。给类对象分配空间并进行默认初始化(一般置为0)。

  • 解析:主要针对字符串常量,将常量池中的符号引用替换为直接引用。

    符号引用:相对的位置

    直接引用:真是的内存地址

    在.class文件中,由于还未加载到内存中,无法确定内存地址,只能使用一个相对偏移量来表示内存地址。当JVM将.class文件进行加载分配了内存地址,此时字符串常量就有了真实地址,然后将一些引用变量中的"符号引用"替换成直接引用。

  • 初始化:对类对象进行初始化。初始化静态成员,执行静态代码块,加载父类.....

双亲委派模型

双亲委派模型描述的是类加载的过程中,如何找.class文件。

JVM在加载.class文件的时候,需要用到类加载器,在JVM中就自带了三个类加载器。

这三个类加载器存在"父子关系",这里的父子关系并不是通过继承形成的,而是对象中有一个引用指向"父类"加载器实例

  • Bootstarp ClassLoader 负责加载标准库中的类(Java标准文档中规定了需要提供哪些基本类)

  • Extension ClassLoader 负责加载JVM扩展库中的类(JVM厂商可能还会添加一些类)

  • Application ClassLoader 负责加载第三方库的类(mysql、jackson.......以及一些自己写的类)

双亲委派模型就描述了类加载的流程:

1.先从Application ClassLoader开始,此时并不会立即搜索第三方库的类,而是先把加载任务委派给"父亲",让父亲先尝试加载

2.到了Extension ClassLoader,此时也不会立即搜索扩展库的类,而是再把加载任务委派给"父亲",让父亲先尝试加载

3.到了Bootstrap ClassLoader,此时Bootstrap ClassLoader没有"父亲"了,只好自己去加载类了。如果找到了这个类,就会进行下一个类的加载,如果没找到了就会回到委派的那个类加载器,即Extension ClassLoader

4.任务回到Exension ClassLoader,此时只能自己去搜索扩展库的类了。如果找到了这个类,就会进行下一个类的加载,如果没找到了就会回到委派的那个类加载器,即Application ClassLoader

5.任务回到Application ClassLoader,此时只能自己去搜索第三方库的类了。

如果找到了这个类,就会进行下一个类的加载,如果没找到了会抛出异常。

总结:双亲委派模型就是一个找.class文件的过程。平时如果我们创建一个跟标准库中名字一样的类,使用的时候依旧是标准库中的那一个,因为双亲委派模型机制,会优先使用标准库的类,这也是这个机制的意义。

类加载时机

类加载使用了懒汉模式,即当使用的时候才会进行加载。

大致可以分为三个时机:

  1. 构造类的实例

  2. 使用了类的静态方法/静态属性

  3. 子类的加载会触发父类

一旦类被加载好了,后续使用就不必再加载了,直接使用即可。

三、JVM垃圾回收机制

在C语言中使用malloc手动申请完内存后需要手动释放,如果光申请而不去释放的话,到达一定程度后,内存被耗尽,程序就会崩溃,但是通过程序猿来手动操作就非常考验个人水平了,无法保证可靠。

Java为了解决上述问题,就引入了垃圾回收机制,自动的把垃圾释放掉。

虽然这个垃圾回收(GC)这个机制非常香,但是也是需要付出代价的,即消耗额外的系统资源和性能开销,同时也出现STW问题。

STW问题:

Stop-The-World 简称 STW,是指在执行垃圾回收的过程冻结所有用户线程的运行,直到垃圾回收线程执行结束。

垃圾回收的主战场在堆区,进行垃圾回收需要两步:判断对象是否为"垃圾"; 释放对象的内存。

判断对象是否为"垃圾"

当一个对象,在后续代码中不会被继续使用了,即这个对象已经没有任何引用指向它了,就可以认为是垃圾了。

如何判断,有如下两种思路:引用计数和可达性分析

引用计数

核心思路:给每个对象里面安排一个计数器,每当有引用指向它的时候,就把计数器的值+1,每当引用被销毁,计数器的值-1.当计数器为0的时候,表示这个对象为垃圾。

优点:简单,好实现。

缺点:空间利用率低,浪费内存空间(当对象本身比较小的时候,会大大降低空间利用率);

​          存在循环引用问题,导致对象不能被正确识别为垃圾。如图:

此时对象A,B在外部已经没有人指向了,即此时我们无法通过代码再去操作A和B了,按理来说已经成为了垃圾,但此时他们的计数器都不为0,无法正确的被识别为垃圾。

在Java中没有使用这种方式,但在Python,PHP的虚拟机中就是使用了引用计数的方式来完成的

可达性分析

在Java中就采用了这个方案。

核心思路:JVM首先会从现有代码中的能直接访问到的引用出发,尝试遍历所有能访问的对象,只要对象能访问到,就会被标记为"可达"。完成整个遍历后,除开可达对象外,其它的也就是不可达对象,也就相当于是垃圾了。

优点:能够很好的解决引用计数中的循环引用问题。

缺点:需要消耗更多的时间。

释放对象内存

释放对象内存主要有三种方式:标记清除;复制算法;标记整理。

标记清除

标记清除是一种直接释放对象内存的方式。这种方式简单粗暴,但会遇到如下问题,即当GC对象是离散,空间不连续的时候:

此时如果直接释放对象的话,就会引起"内存碎片"。在申请内存空间的时候都是申请一块连续的内存,当使用标记清除直接释放的话,此时如果申请的内存空间比正GC对象大的话,就无法使用这块已经被回收的内存。

例如:假设上图中的每个GC对象的大小是1MB,但我们此时要申请一个2MB的内存空间,由于每个GC对象内存的前后的内存被占用了,我们就无法申请到空间.

复制算法

复制算法的核心思路是将空间分成两份,把有效对象复制到另一部分内存空间,来避免内存空间。

先是将左侧有效对象进行复制,放到右侧,然后再释放内存,当用了一段时间后,右侧也会有许多需要GC的对象,此时就将有效对象复制到左侧,循环往复。

虽然这种方式能有效的解决内存碎片问题,但当需要复制的对象内容比较多,就会引发不小的开销,并且由于会将内存进行划分,也会造成内存利用低的问题。

标记整理

标记整理是使用顺序表删除元素的思路。

每当要GC一个对象,会将后面的对象往前搬运。

这种方式,不仅可以解决内存碎片问题,也解决了内存利用率低的问题,但是会涉及频繁搬运的问题,这就会带来不小的开销。


分代回收

设计JVM的大佬集百家之长,搞了一个综合性的解决方法:分代回收。

分代回收是基于"一个对象存在的越久,那么它将继续存在的可能性就越高"的事实,然后对每个对象使用"年龄"标记,根据年龄来制定不同的回收策略。

分代回收将整个堆分成了两部分:新生代和老年代。在新生代中又划分了两个不同的区域:伊甸区和幸存区。

在新生代中以复制算法为主,在老年代中以标记整理算法为主。

伊甸区中存放的是新生的对象,在经过一轮的GC后,没有被回收的对象就会被通过复制算法,复制到幸存区中。

幸存区中又划分了两块不同的空间,用来针对后续的复制算法,当第二轮GC后,没有被回收的对象就会被复制到幸存区中另一块空间。

如果一个对象在幸存区中存活了好多轮都没有挂,这个对象的年龄就比较大了,就会被复制到老年代中。

在新生代中每一轮GC留下的对象并不会很多,所以进行复制算法的开销并不会很大,而在老年代中,对象比较重要,所以销毁的也很少,此时标记整理开销也不会很大。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据库——多表查询概述

与单表查询不同,多表查询是从多张表中查找数据。例如: select * from user,course; 得到一张有36条数据的表,这是因为12条数据的user表与3条数据的course表进行了笛卡尔积运算,但是在多表查询中,往往需要消除笛卡尔积带…

MySQL 与 PostgreSQL 在 SQL 方面的关键对比二(功能篇)

目录 1 详细示例 1.1自动增量列 1.2 字符串连接 1.3 JSON 支持 2 总结 MySQL 和 PostgreSQL 是两种流行的开源关系数据库管理系统(RDBMS)。尽管它们在许多方面相似,但在 SQL 语法和功能上存在一些显著差异。 以下SQL语句的执行如果需要开…

YoloV8改进策略:Block篇|MobileNetV4——移动生态系统的通用模型

文章目录 摘要1、引言2、相关工作3、硬件无关的帕累托效率4、通用反向瓶颈5、Mobile MQA6、MNv4模型设计6.1、精炼NAS以增强架构6.2、MNv4模型的优化 7、结果7.1、ImageNet分类 8、增强蒸馏方案9、结论10、致谢A、搜索空间细节B、基准测试方法论C、ImageNet-1k分类任务的训练设…

springboot启动报端口被占用,修改端口还是报被占用,如何处理?

第一种方式: 通过cmd查看是否有程序占用端口 netstat -ano| findstr 端口号 杀死进程 taskkill -f -pid 进程号 如果未看到有程序占用该端口说明不是这个原因 第二种方式: 打开任务管理器 查看是否进程占用对应端口,有就关闭进程 第三种…

视觉SLAM十四讲:从理论到实践(Chapter8:视觉里程计2)

前言 学习笔记,仅供学习,不做商用,如有侵权,联系我删除即可 一、目标 1.理解光流法跟踪特征点的原理。 2.理解直接法是如何估计相机位姿的。 3.实现多层直接法的计算。 特征点法存在缺陷: 二、光流(Optical Flow) …

nodeJS社区新冠人群管理与老人疫苗小程序-计算机毕业设计源码65190

目 录 摘要 1 绪论 1.1背景及意义 1.2国内外研究慨况 1.3B/S体系工作原理 1.4node.js主要功能 2 1.5论文结构与章节安排 3 2 社区新冠人群管理与老人疫苗小程序分析 4 2.1 可行性分析 4 2.2 系统流程分析 4 2.2.1数据增加流程 5 2.3.2数据修改流程 5 2.3.3数据删除流程 5…

【会议征稿,IEEE出版】第六届电子与通信,网络与计算机技术国际学术会议(ECNCT 2024,7月19-21)

第六届电子与通信,网络与计算机技术国际学术会议 (ECNCT 2024)将于 2024年7月19日-21日 在 中国广州 举办, 为期三天。 会议由广东工业大学自动化学院主办,会议将安排主旨报告,口头报告以及海报展示&#…

人类语言处理nlp部分笔记——二、BERT和它的家族-介绍和微调

参考自李宏毅课程-人类语言处理 二、BERT和它的家族-介绍和微调 1. What is pre-train model 这里所说的pre-train model是输入一串tokens,能够输出一串vectors,且每个vector可以表示对应的语义的模型,这些vectors也被称作为embeddings。以…

假设检验学习笔记

1. 假设检验的基本概念 1.1. 原假设(零假设) 对总体的分布所作的假设用表示,并称为原假设或零假设 在总体分布类型已知的情况下,仅仅涉及总体分布中未知参数的统计假设,称为参数假设 在总体分布类型未知的情况下&#…

抱抱脸上第一的开原模型Qwen2-72B;腾讯开源人像照片生成视频的模型;Facebook开源翻译模型;智谱 AI 推出的最新一代预训练模型

✨ 1: Qwen2 Qwen2 是一种多语言预训练和指令调优的语言模型,支持128K上下文长度并在多项基准测试中表现优异。 Qwen2(全称“Qwen Qwen”,简称Qwen)是一个先进的大语言模型家族,在其前身Qwen1.5的基础上进行了重大提…

安卓手机平板使用JuiceSSH无公网IP远程连接本地服务器详细流程

文章目录 前言1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 前言 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? 本文就和大家分享一下如何使用 cpolarJuiceSSH 实现手机端远程连接Linux…

多目标应用:MOHHO多目标哈里斯鹰优化算法求解无人机三维路径规划(MATLAB代码)

详细介绍 多目标应用:MOHHO多目标哈里斯鹰优化算法求解无人机三维路径规划(MATLAB代码)-CSDN博客 一次运行结果 完整MATLAB代码

四十、openlayers官网示例External map解析——打开一个外部小窗口展示地图

官网demo地址: External map 这篇展示了外部窗口打开地图视图。 首先先初始化地图。 创建了一个UnusableMask类继承Control用来做主页面地图放进小窗口后的遮罩层,设置了自定义属性hidden来控制遮罩层的显隐。 initMap() {class UnusableMask extend…

【Spring Cloud】Gateway 服务网关核心架构的执行流程和断言

文章目录 基本概念执行流程断言内置路由断言工厂自定义路由断言工厂 总结 基本概念 路由(Route)是gateway中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面的几个信息: id:路由标识符,区别于其他Route。uri&…

营养调控微生物及代谢产物:对免疫和炎症的影响

谷禾健康 菌群.营养.炎症.免疫 营养在整个生命周期中对免疫和炎症以及最终的健康有深远影响。最新研究表明,饮食对肠道微生物组成和代谢产物具有显著影响,从而对宿主免疫和炎症产生重要影响。 研究发现,我们日常饮食中的特定食物成分和代谢产…

Linux-vi编辑器命令使用

一、初始-vi 1、 vi-打开文件并且定位行 有可能会遇到打开一个文件,并定位到指定行的情况 例如,知道某一行代码有错误,可以快速定位到出错代码的位置 可以使用以下命令打开文件$ vi 文件名 行数 提示:如果只带上 而不指定行号&…

(C++) 函数重载机制

文章目录 🔢前言🕹️参考资料🕹️实例代码 🔢重载机制🥇名称查找🥈模板函数处理🥉重载决议 END关注我 🔢前言 在C中函数重载是一个非常强大由复杂的问题。 在C中本身就有许多函数机…

外汇天眼:金融服务补偿计划(FSCS)确认已任命清算人为TenetConnect Services有限公司

2024年6月5日,Tenet Group有限公司的董事们任命了Interpath有限公司的Ed Boyle、Howard Smith和Rob Spence为联合清算人。Ed Boyle和Rob Spence也被任命为其子公司Tenet有限公司、TenetConnect有限公司和TenetConnect Services有限公司的联合清算人。Tenet Mortgage…

手把手Linux高可hadoop集群的搭建

高可用集群的搭建 在搭建高可用集群之前,如果搭建了完全分布式hadoop,先执行stop-all.sh停掉所有的服务,只保留jdk和zookeeper的2个服务,然后再去搭建。 目标: 高可用集群简介部署Hadoop高可用集群 一.…

备战618!各广告平台SDK版本更新;最新支持eCPR指标;新增自动创建广告源平台 | TopOn产品更新

「TopPro 每月产品速递」是由TopOn最新推出的产品专栏,将会以月为周期梳理TopOn最新产品动态,致力于为互联网从业者提供优质服务,引领行业产品发展。 TopPro | 3~5月产品速递 2024.03.01-05.30 01 eCPR指标支持 // 功能描述 TopOn后台支…