JVM常见知识点

news2025/3/4 12:31:56

在《深入理解Java虚拟机》一书中,介绍了JVM的相关特性。

1、JVM的内存区域划分

在真实的操作系统中,对于地址空间进行了分区域的设计,由于JVM是仿照真实的机器进行设计的,那么也进行了分区域的设计。核心区域有四个,分别为程序计数器、元数据区、栈、堆。此处的栈和堆与数据结构中的栈和堆不一样。

元数据区和堆,是整个 java 进程共用一份的,程序计数器和栈,在一个进程中可能有多份,即每个进程都有一份。

1)程序计数器

很小的一块地址,用来记录指令运行到哪个地址了。

2)元数据区

保存当前类被加载好的数据。

.java 文件需要先被编译为 .class 文件,再将 .class 文件加载到内存中。

元数据区保存类的名字、类的可见性、类的继承关系、实现的接口等。

元数据区通常保存静态成员变量。

3)栈

保存方法的调用关系,此处使用了数据结构中的栈来进行保存。将先执行到的方法先入栈,后执行方法后入栈。

比如,在 main 方法中有 test 方法,当开始运行时,就会先将 main 入栈,当代码执行到 test 方法后,就会将 test 方法入栈,当test 方法运行结束后,就会返回到 main 中继续往下执行。图示如下:

栈中的每个方格就是一个栈帧,栈帧中保存了该方法的参数、局部变量、返回值、返回的地址(即该方法结束后应该返回到哪个方法继续执行)。

栈空间通常只有几MB、几十MB。

当程序出现异常(如递归代码有问题)时,有可能会出现栈溢出(StackOverFlow)的情况。

栈通常保存局部变量。

4)堆

堆是 JVM 中最大的内存空间。用来保存 new 出来的对象的。

2、类加载机制

1)类加载的步骤

类加载一共有三大阶段,第二阶段又分为三个步骤。

① 加载,找到 .class 文件

根据类的全限定名(包名 + 类名,如 java.lang.String)找到后打开文件,将文件内容读取到内u村中;

②验证

校验 .class 文件中的内容是否合法,并将文件中的内容转化为结构化的数据;

③准备

给类对象申请内存空间,即全 0 的空间;

④解析

针对字符串常量进行初始化。将文件中的字符串常量放到元数据区中。

⑤初始化

针对类对象进行最终的初始化,包括针对类对象各种属性的填充和类的静态成员。

若该类的父类还没有加载,此环节也会触发父类的加载。

上面的五步中,2、3、4步为第二阶段。

2)双亲委派模型

在类加载的第一步中,需要根据类的全限定名找到 .class 文件,这就涉及到双亲委派模型。

在进行类加载时,需要使用到类加载器。JVM 默认提供三种类加载器,分别为 BootstrapClassLoader(Java 标准库目录)、ExtensionClassLoader(Java 拓展库目录)、ApplicationClassLoader(Java 第三方库 / 当前项目)。BootstrapClassLoader 是 ExtensionClassLoader 的父类,ExtensionClassLoader 是 ApplicationClassLoader 的父类。此处的父类不是父子关系,而是通过 prant 引用进行指向。

在进行类加载时,将 ApplicationClassLoader 作为入口开始,把“类加载”的任务交给 ExtensionClassLoader 去完成,但 ExtensionClassLoader 也不会马上进行查找,而是将“类加载”的任务交给 BootstrapClassLoader 去完成。然后 BootstrapClassLoader 就会在标准库范围进行查找该 .class 文件是否存在,若存在,就加载,若不存在,就把任务返回给 ExtensionClassLoader ,在拓展库中进行查找,若找到就加载,若没有找到就将任务返回给 ApplicationClassLoader,在第三方库 / 当前项目进行查找,若找到就加载,若没找到,就会抛出 ClassNotFoundException 异常。流程图如下:

3、垃圾回收器 (GC)

由于手动进行内存释放太麻烦,并且如果忘记释放就会出现内存泄漏,于是,Java使用 GC 来进行垃圾回收。这里指的垃圾通常为对象,若这个对象在之后的代码中不会用到,就会被视为“垃圾”,进而被释放内存。

垃圾回收器回收的是堆上的内存。

使用 GC 释放垃圾分为以下两步:找到垃圾、释放垃圾。

1)找到垃圾

找到垃圾即找到不使用的类对象。有下面两个方法:

①引用计数(Python等语言使用)

在每次创建对象时,都使用一块小的内存空间来保存一个整数,这个整数就是当前对象有都少个引用指向它。每次进行引用赋值时,都会触发这个整数的修改。若整数变为0,就说明没有引用指向这个对象,即这个对象变成了垃圾。

但是这个方法也有缺陷,即:

内存消耗更多,当对象本身较小时,消耗的空间比例就更大;

可能会出现“循环引用”的问题。(需要搭配其他的方案来解决该问题)。

可达性分析(Java使用)

由于引用计数需要消耗空间,于是可达性分析就用时间来换空间。

以代码中的一些特定对象作为起点,对其他对象进行遍历,将每次遍历到的对象设为可达,遍历完成后,不可达的对象就是已经没有引用指向的对象,即垃圾,需要被回收掉。

这里的遍历很像数或图的遍历。现有下面的二叉树:

这里的每一个结点都代表一个对象。当将 c.right = null 时,在从 a 开始遍历时,f 结点就遍历不到,这时 f 就是不可达的,就会将 f 回收掉;当将 a.right = null 时 ,当从 a 开始遍历时,c 结点就是不可达的,也就导致 f 结点不可达,就会将 c 和 f 回收掉。

缺点:每次需要将所有对象遍历一遍,需要配消耗较大的时间和资源。

2)释放垃圾

①标记-清除

把垃圾对象的内存直接释放,但是这样做会产生内存碎片问题。

图中b、d、f、h是垃圾,若将其直接释放,就会导致释放后的内存空间是零散的,但由于申请内存时需要连续的内存,那么这些被释放的内存空间就会无法使用(需要的申请内存大于碎片的内存),导致内存申请失败。

②复制算法

在使用一部分内存时,每次只使用这一部分的一半内存,将创建的对象放在这一半内存上,若有的对象需要被回收,就会将不是垃圾的对象复制到另一半内存上,再将原来那一部分的对象直接回收。

这种做法就避免了产生碎片内存的问题。但也有缺点:

空间利用率低;

一旦不是垃圾的对象较多或需要复制的对象较大,就会提高复制成本,降低程序运行的效率。

③标记-整理

如上图,现b、d、f、h都是垃圾对象,于是就会将其他不是垃圾的对象向前移,移动后的结果如下图:

 之后就会将e、f、g、h直接释放。

这样做即避免出现内存碎片问题,又保证了内存的利用率。但是依然会涉及到对象的复制,若对象较多或较大,就会提高复制成本。

④将上面的三种方法结合起来

使用“代”来表示对象的年龄,即每一次遍历后若不是垃圾就加1,初始为0。

GC将内存区域划分为若干个区域,有新生代区、老年代区,新生代区中又包含伊甸区、幸存区。

伊甸区有幸存区的空间比例通常为8:1:1。

针对不同年龄的对象使用的测率不同。

若为新生代对象,就放到伊甸区中,由于绝大部分新生代对象都会在第一轮GC中变为垃圾对象,于是幸存区就比伊甸区小。 在进行遍历时,若新生代对象不是垃圾,就会放到幸存区,,若是垃圾就会直接释放。由于需要复制的对象较少,就使得复制的开销相对较小。

幸存区中的对象也需要进行遍历,若有的对象时垃圾,就会将不是垃圾的对象复制到另一个幸存区中,再将幸存区中的对象全部释放。

若某个对象经过多轮的遍历有都还是有用的,这时就会将该对象放到老年代中。由于老年代对象的生命周期较长,就使得整理的开销也较小。

于是每个对象都会经历以下几个时期:

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

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

相关文章

类和对象(4)——多态:方法重写与动态绑定、向上转型和向下转型、多态的实现条件

目录 1. 向上转型和向下转型 1.1 向上转型 1.2 向下转型 1.3 instanceof关键字 2. 重写(overidde) 2.1 方法重写的规则 2.1.1 基础规则 2.1.2 深层规则 2.2 三种不能重写的方法 final修饰 private修饰 static修饰 3. 动态绑定 3.1 动态绑…

系统思考—问题分析

很多中小企业都在面对转型的难题:市场变化快,资源有限,团队协作不畅……这些问题似乎总是困扰着我们。就像最近和一位企业主交流时,他提到:“我们团队每天都很忙,但效率始终没见提升,感觉像是在…

Midscene.js:重新定义UI自动化的新时代工具

前言 Midscene.js 是一个创新的、面向开发者的 UI 自动化解决方案,并通过人工智能技术简化自动化脚本的编写与维护。 它提供了三种核心方法——交互(.ai, .aiAction)、提取(.aiQuery)和断言(.aiAssert&am…

go单元测试和基准测试

1、单元测试和基准测试 单元测试和基准测试代码开发中的重要环节,良好的单元测试和基准测试,能提升开发质量,对整体开发有非常重要的重要,下面介绍单元测试和基准测试的写法。 2、单元测试和基准测试写法 以排序基本排序算法&a…

Nuxt:利用public-ip这个npm包来获取公网IP

目录 一、安装public-ip包1.在Vue组件中使用2.在Nuxt.js插件中使用public-ip 一、安装public-ip包 npm install public-ip1.在Vue组件中使用 你可以在Nuxt.js的任意组件或者插件中使用public-ip来获取公网IP。下面是在一个Vue组件中如何使用它的例子&#xff1a; <template…

day7手机拍照装备

对焦对不上&#xff1a;1、光太暗&#xff1b;2、离太近&#xff1b;3、颜色太单一没有区分点 滤镜可以后期P 渐变灰滤镜&#xff1a;均衡色彩&#xff0c;暗的地方亮一些&#xff0c;亮的地方暗一些 中灰滤镜&#xff1a;减少光差 手机支架&#xff1a;最基本70cm即可 手…

LLM - 大模型 ScallingLaws 的指导模型设计与实验环境(PLM) 教程(4)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/145323420 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Scalin…

【Linux网络编程】传输层协议

目录 一&#xff0c;传输层的介绍 二&#xff0c;UDP协议 2-1&#xff0c;UDP的特点 2-2&#xff0c;UDP协议端格式 三&#xff0c;TCP协议 3-1&#xff0c;TCP报文格式 3-2&#xff0c;TCP三次握手 3-3&#xff0c;TCP四次挥手 3-4&#xff0c;滑动窗口 3-5&#xf…

FreeRtos的使用教程

定义&#xff1a; RTOS实时操作系统, (Real Time Operating System), 指的是当外界事件发生时, 能够有够快的响应速度,调度一切可利用的资源, 控制实时任务协调一致的运行。 特点&#xff1a; 支持多任务管理&#xff0c; 处理多个事件&#xff0c; 实现更复杂的逻辑。 与计算…

基于Ubuntu交叉编译ZLMediaKit

一、确保基于虚拟机VMVare的Ubuntu能正常上网 1、设置WIFI硬件无线网卡上网 菜单栏的“编辑”->选择“虚拟网络编辑器”&#xff0c;在弹出的窗口中&#xff0c;点击桥接模式的VMnet0&#xff0c;然后在下方选择“桥接模式”&#xff0c;网卡下拉栏&#xff0c;选择你目前…

【PyTorch][chapter 29][李宏毅深度学习]Fine-tuning LLM

参考&#xff1a; https://www.youtube.com/watch?veC6Hd1hFvos 目录&#xff1a; 什么是 Fine-tune 为什么需要Fine-tuning 如何进行Fine-tune Fine-tuning- Supervised Fine-tuning 流程 Fine-tuning参数训练的常用方案 LORA 简介 示例代码 一 什么是 Fine-tune …

数字图像处理:实验七

uu们&#xff01;这是我们目前数字图像系列的最后一张&#xff0c;之后有关人工智能结合的数字图像处理咸鱼哥正在学习和创作中&#xff0c;所以还请大家给咸鱼哥点时间&#xff0c;同时也提前预祝大家2025年新春快乐&#xff01;&#xff08;咸鱼哥真诚的祝愿每一个人&#xf…

通义灵码插件保姆级教学-IDEA(安装及使用)

一、JetBrains IDEA 中安装指南 官方下载指南&#xff1a;通义灵码安装教程-阿里云 步骤 1&#xff1a;准备工作 操作系统&#xff1a;Windows 7 及以上、macOS、Linux&#xff1b; 下载并安装兼容的 JetBrains IDEs 2020.3 及以上版本&#xff0c;通义灵码与以下 IDE 兼容&…

利用双指针一次遍历实现”找到“并”删除“单链表倒数第K个节点(力扣题目为例)

Problem: 19. 删除链表的倒数第 N 个结点 文章目录 题目描述思路复杂度Code 题目描述 思路 1.欲找到倒数第k个节点&#xff0c;即是找到正数的第n-k1、其中n为单链表中节点的个数个节点。 2.为实现只遍历一次单链表&#xff0c;我们先可以使一个指针p1指向链表头部再让其先走k步…

2025美赛倒计时,数学建模五类模型40+常用算法及算法手册汇总

数学建模美赛倒计时&#xff0c;对于第一次参加竞赛且没有相关基础知识的同学来讲&#xff0c;掌握数学建模常用经典的模型算法知识&#xff0c;并熟练使用相关软件进行建模是关键。本文将介绍一些常用的模型算法&#xff0c;以及软件操作教程。 数学建模常用模型包括&#xf…

前端【10】jQuery DOM 操作

目录 jquery捕获查取 获得内容 - text()、html() 以及 val() 获取属性 - attr() ​编辑 jQuery 修改/设置内容和属性 设置内容 - text()、html() 以及 val() 设置属性 - attr() jQuery添加元素 jQuery - 删除元素 前端【9】初识jQuery&#xff1a;让JavaScript变得更简…

汇编的使用总结

一、汇编的组成 1、汇编指令&#xff08;指令集&#xff09; 数据处理指令: 数据搬移指令 数据移位指令 位运算指令 算术运算指令 比较指令 跳转指令 内存读写指令 状态寄存器传送指令 异常产生指令等 2、伪指令 不是汇编指令&#xff0c;但是可以起到指令的作用&#xff0c;伪…

想品客老师的第七天:闭包和作用域

闭包之前的内容写在这里 环境、作用域、回收 首先还是数据的回收问题&#xff0c;全局变量一般都是通过关闭页面回收的&#xff1b;而局部变量的值不用了&#xff0c;会被自动回收掉 像这种写在全局里的就不会被主动回收捏&#xff1a; let title 荷叶饭function fn() {ale…

速通Docker === Docker 镜像分层存储机制

目录 分层存储的概念 分层存储的实现 镜像层 容器层 分层存储的优势 1. 镜像轻量化 2. 快速构建与部署 3. 高效的镜像共享 4. 版本控制 分层存储的示例 容器层的临时性与数据持久化 总结 Docker 的分层存储机制是其核心特性之一&#xff0c;它使得镜像的构建、共享和…

开源智慧园区管理系统对比五款主流产品探索智能运营新模式

内容概要 在这个数字化迅速发展的时代&#xff0c;园区管理也迎来了全新的机遇和挑战。众所周知&#xff0c;开源智慧园区管理系统作为一种创新解决方案&#xff0c;正逐步打破传统管理的局限性。它的开放性不仅使得系统可以根据具体需求进行灵活调整&#xff0c;也为用户提供…