JVM常见知识点
在《深入理解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中变为垃圾对象,于是幸存区就比伊甸区小。 在进行遍历时,若新生代对象不是垃圾,就会放到幸存区,,若是垃圾就会直接释放。由于需要复制的对象较少,就使得复制的开销相对较小。
幸存区中的对象也需要进行遍历,若有的对象时垃圾,就会将不是垃圾的对象复制到另一个幸存区中,再将幸存区中的对象全部释放。
若某个对象经过多轮的遍历有都还是有用的,这时就会将该对象放到老年代中。由于老年代对象的生命周期较长,就使得整理的开销也较小。
于是每个对象都会经历以下几个时期:
相关文章:

JVM常见知识点
在《深入理解Java虚拟机》一书中,介绍了JVM的相关特性。 1、JVM的内存区域划分 在真实的操作系统中,对于地址空间进行了分区域的设计,由于JVM是仿照真实的机器进行设计的,那么也进行了分区域的设计。核心区域有四个,…...

深入探索 Vue 3 Markdown 编辑器:高级功能与实现
目录 1. 为什么选择 Markdown 编辑器?2. 选择合适的 Markdown 编辑器3. 安装与基本配置安装 配置 Markdown 编辑器代码说明 4. 高级功能实现4.1 实时预览与双向绑定4.2 插入图片和图像上传安装图像上传插件配置图像上传插件 4.3 数学公式支持安装 KaTeX配置 KaTeX 插…...

vscode无法格式化go代码的问题
CTRLshiftp 点击Go:Install/Update Tools 点击全选,OK!...

《Java程序设计》课程考核试卷
一、单项选择题(本大题共10个小题,每小题2分,共20分) 1.下列用来编译Java源文件为字节码文件的工具是( )。 A.java B.javadoc C.jar D.javac 2…...
one-hot (独热编码)
一、目的 假设我们现在需要对猫、 狗、 人这三个类别进行分类。 若以 0 代表猫, 以 1 代表狗, 以 2 代表人,会发现那么猫和狗之间距离为 1, 狗和人之间距离为 1, 而猫和人之间距离为 2。 假设真实标签是猫࿰…...

寒假1.23
题解 web:[极客大挑战 2019]Secret File(文件包含漏洞) 打开链接是一个普通的文字界面 查看一下源代码 发现一个链接,点进去看看 再点一次看看,没什么用 仔细看,有一个问题,当点击./action.ph…...

unity 粒子系统设置触发
1、勾选Triggers选项 2、将作为触发器的物体拉入队列当中,物体上必须挂载collider 3、将想要触发的方式(Inide、Outside、Enter和Exit)选择为”Callback“,其他默认为”Ignore“ 4、Collider Query Mode 设置为All:…...

【C++】类和对象(五)
1、初始化列表 作用:C提供了初始化列表语法,用来初始化属性。 语法: 构造函数():属性1(值1),属性2(值2)...{}示例: #include<i…...

超分辨率体积重建实现术前前列腺MRI和大病理切片组织病理学图像的3D配准
摘要: 磁共振成像(MRI)在前列腺癌诊断和治疗中的应用正在迅速增加。然而,在MRI上识别癌症的存在和范围仍然具有挑战性,导致即使是专家放射科医生在检测结果上也存在高度变异性。提高MRI上的癌症检测能力对于减少这种变异性并最大化MRI的临床效用至关重要。迄今为止,这种改…...

第13章 深入volatile关键字(Java高并发编程详解:多线程与系统设计)
1.并发编程的三个重要特性 并发编程有三个至关重要的特性,分别是原子性、有序性和可见性 1.1 原子性 所谓原子性是指在一次的操作或者多次操作中,要么所有的操作全部都得到了执行并 且不会受到任何因素的干扰而中断,要么所有的操作都不执行…...

[STM32 标准库]定时器输出PWM配置流程 PWM模式解析
前言: 本文内容基本来自江协,整理起来方便日后开发使用。MCU:STM32F103C8T6。 一、配置流程 1、开启GPIO,TIM的时钟 /*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟RCC_APB2PeriphClockC…...

web3py+flask+ganache的智能合约教育平台
最近在学习web3的接口文档,使用web3pyflaskganache写了一个简易的智能合约教育平台,语言用的是python,ganche直接使用的本地区块链网络,用web3py进行交互。 代码逻辑不难,可以私信或者到我的闲鱼号夏沫mds获取我的代码…...

< OS 有关 > 阿里云:轻量应用服务器 的使用 :轻量化 阿里云 vpm 主机
原因: < OS 有关 > 阿里云:轻量应用服务器 的使用 :从新开始 配置 SSH 主机名 DNS Tailscale 更新OS安装包 最主要是 清除阿里云客户端这个性能杀手-CSDN博客 防止 I/O 祸害系统 操作: 查看进程&#x…...

【技术】TensorRT 10.7 安装指南(Ubuntu22.04)
原文链接:https://mengwoods.github.io/post/tech/008-tensorrt-installation/ 本文安装的版本如下: Ubuntu 22.04 Nvidia Driver 538.78 CUDA 12.2 cuDNN 8.9.7 TensorRT 10.7 安装前的准备(可选) 在安装新版本之前…...

Linux 权限管理
hello!这里是敲代码的小董,很荣幸您阅读此文,本文只是自己在学习Linux过程中的笔记,如有不足,期待您的评论指点和关注,欢迎欢迎~~ ✨✨个人主页:敲代码的小董 💗💗系列专…...

8.2 从看图识字到智能解读:GPT-4 with Vision 开启多模态 AI 新纪元
从看图识字到智能解读:GPT-4 with Vision 开启多模态 AI 新纪元 引言:AI 的多模态跃迁 随着人工智能技术的快速发展,我们正迈入一个新的智能交互时代。传统的 AI 模型主要聚焦于文本处理,而多模态 AI 模型如 GPT-4 with Vision(GPT-4V) 则能够同时处理图像和文本。GPT-4…...

差分轮算法-两个轮子计算速度的方法-阿克曼四轮小车计算方法
四轮驱小车的话: 转向角度计算方法:float turning_angle z_angular / x_linear; // 转向角度,单位为弧度 速度的话直接用线速度 两轮驱动小车: 计算公式: leftSpeed x_linear - z_angular * ORIGINBOT_WHEEL_TRACK /…...

使用.NET 8构建高效的时间日期帮助类
使用.NET 8构建高效的时间日期帮助类 在现代Web应用程序中,处理日期和时间是一个常见的需求。无论是记录日志、生成报告还是进行数据分析,正确处理日期和时间对于确保数据的准确性和一致性至关重要。本文将详细介绍如何使用ASP.NET Core和C#构建一个高效…...

学习std::is_base_of笔记
1、std::is_base_of简介 在现代 C 中,模板元编程(Template Metaprogramming)是一种非常强大的编程技巧,它让我们能够在编译期进行类型推导和约束。而 std::is_base_of 是一个重要的工具,可以用来检查一个类型是否是另…...

第 25 场 蓝桥月赛
3.过年【算法赛】 - 蓝桥云课 问题描述 蓝桥村的村民们正准备迎接新年。他们计划宰杀 N 头猪,以庆祝一整年的辛勤劳作和丰收。每头猪的初始位置位于下标 xi,所有 xi 均为偶数,保证没有两头猪初始位置相同。 当猪意识到人类打算宰杀它们…...

【设计模式-行为型】访问者模式
一、什么是访问者模式 说起来访问者模式,其实很少用。我一直在思考该用什么样的例子把这个设计模式表述清晰,最近突然想到一个例子也许他就是访问者。港片有过很辉煌的年代,小的时候一直在看港片觉得拍的非常好,而且演员的演技也在…...

无人机微波图像传输数据链技术详解
无人机微波图像传输数据链技术是无人机通信系统中的关键组成部分,它确保了无人机与地面站之间高效、可靠的图像数据传输。以下是对该技术的详细解析: 一、技术原理 无人机微波图像传输数据链主要基于微波通信技术实现。在数据链路中,图像数…...

SpringCloud系列教程:微服务的未来(十七)监听Nacos配置变更、更新路由、实现动态路由
前言 在微服务架构中,API 网关是各个服务之间的入口点,承担着路由、负载均衡、安全认证等重要功能。为了实现动态的路由配置管理,通常需要通过中心化的配置管理系统来实现灵活的路由更新,而无需重启网关服务。Nacos 作为一个开源…...

【QT】 控件 -- 显示类
🔥 目录 [TOC]( 🔥 目录) 1. 前言 2. 显示类控件2.1 Label 1、显示不同文本2、显示图片3、文本对齐、自动换行、缩进、边距4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥 1. 前言 之前我在上一篇文章【QT】…...

反馈驱动、上下文学习、多语言检索增强等 | Big Model Weekly 第55期
点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 01 A Bayesian Approach to Harnessing the Power of LLMs in Authorship Attribution 传统方法严重依赖手动特征,无法捕捉长距离相关性,限制了其有效性。最近的研究利用预训练语言模型的…...

CF 41A.Translation(Java实现)
题目分析 根据示例千言万语一句话,reverse 思路分析 将读取的值分ab,再将b.reverse和a比较,一样就YES 代码 import java.util.*;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);String …...

14【学历和能力哪个更重要】
这是很多学习的人有的一个疑问,并提出想让我发表下看法,前面一直没空,我刚好完结了一个项目,最近又有时间更新图文课程了,就展开来讲讲 主流的说法有2个 1:学历重要,依据是很多公司招聘都有学历…...

Learning Vue 读书笔记 Chapter 2
2. Vue 基本工作原理 2.1 Virtual DOM 概念: DOM: DOM以内存中树状数据结构的形式,代表了网页上的HTML(或XML)文档内容。它充当了一个编程接口,将网页与实际的编程代码(如JavaScript)连接起来…...

SpringBoot支持动态更新配置文件参数
前言 博主介绍:✌目前全网粉丝3W,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容:Java后端、大数据、算法、分布式微服务、中间件、前端、运维等。 博主所有博客文件…...

开发技巧,vue 中的动态组件的引用 component + is
在项目中很多时候有切换 tab 的场景,一般来说都是用 v-if 或者 v-show 然后根据各种条件来控制显示隐藏。 其实我们可以使用 vue 中的动态组件,也能实现这个效果 <!-- currentTab 改变时组件也改变 --> <component :is"currentTab"…...