JVM 双亲委派模型以及垃圾回收机制
目录
1. JVM 内存区域划分
2. JVM 中类加载的过程
1) 类加载的基本流程
2) 双亲委派模型
3. JVM 中垃圾回收机制
1) 找到垃圾
a) 引用计数
b) 可达性分析
2) 释放垃圾
1. JVM 内存区域划分
一个运行起来的 Java 进程,其实就是一个 JVM 虚拟机。
而进程是资源分配的基本单位,所以 JVM 就首先会申请一大块内存,然后把这个内存划分成不同的区域,每个区域都有不同的作用。
JVM 内存区域划分成以下四个部分:
1. 方法区 (1.7 及之前) / 元数据区 (1.8 开始)
方法区存储的内容,就是类对象。( .class 文件加载到内存之后,就成了类对象)
2. 堆
这里存储的内容,就是代码中 new 的对象。
堆是占据空间最大的区域。
3. 虚拟机栈(就是平常我们所说的栈)
这里存储的内容,就是代码执行过程中,方法之间的调用关系。
4. 程序计数器
是个比较小的空间,主要用来存放一个 "地址",这个地址,就表示了下一条要执行的指令,在内存中的哪个地方(方法区里)。
每个方法,里面的指令,都是以二进制的形式, 保存到类对象中的。
刚开始调用方法的时候,程序计数器记录的就是方法的入口的地址。
随着一条一条的执行指令,每执行一条指令,程序计数器的值都会自动更新,去指向下一条指令。
程序计数器和虚拟机栈是每个线程都有一份,而堆和方法区在 JVM 进程中是只有一份的。
在 Java 里,每个线程都有自己私有的栈空间。
2. JVM 中类加载的过程
1) 类加载的基本流程
java 代码会被编译成 .class 文件(包含了一些字节码),java 程序想要运行起来,就需要让 JVM 读取到这些 .class 文件,并把里面的内容,构造成类对象,保存到内存的方法区中。
官方文档把类加载的过程主要分成了 5 个步骤。
1. 加载:找到 .class 文件,打开文件,读取文件内容。
往往代码中,会给定某个类的 "全限定类名"(比如 java.lang.String,java.util.ArrayList) ,JVM 就会根据这个类名,在一些指定的目录范围内查找。
2. 验证: .class 文件是一个二进制的格式。(某个字节,都是有某些特定含义的),就需要验证你当前读到的这个格式是否符合要求。
3. 准备:给类对象分配内存空间(最终的目标,是要构造出类对象)
这里只是分配空间,还没有初始化,此时这个空间上的内存的数值,就是全 0 的,此时如果尝试打印类的 static 成员,就是全 0 的。
4. 解析:针对类对象中包含的字符串常量进行处理,进行一些初始化操作。
java 代码中用到的字符串常量,在编译之后,也会进入到 .class 文件中。
5. 初始化:针对类对象进行初始化。
把类对象中需要的各个属性都设置好。
还需要初始化号 static 成员
还需要执行静态代码块
以及可能还需要加载一下父类。
总结类加载的基本流程:
1. 加载:找到 .class 文件,打开 .class 文件,读取 .class 文件
2. 验证:验证当前 .class 文件格式是否正确
3. 准备:给类对象分配内存空间
4. 解析:将符号引用替换成直接引用
5. 初始化:初始化类对象
2) 双亲委派模型
属于类加载中第一个步骤 "加载" 中的一个环节,是负责根据全限定类名,来找到 .class 文件的。
类加载器,是 JVM 中的一个模块(专门负责类加载的操作)。
JVM 中,内置了三个类加载器:
1. BootStrap ClassLoader 爷
2. Extension ClassLoader 父
3. Application ClassLoader 子
这个父子关系,不是继承构成的,而是这几个 ClassLoader 里有一个 parent 这样的属性,指向了一个 父 "类加载器"。
程序员也可以手动创建出新的类加载器。
所以说,双亲委派模型,就是一个查找优先级的问题,先找标准库,再找扩展库,最后找第三方库。
3. JVM 中垃圾回收机制
在 Java 中,new 一个对象,就是 "动态内存申请",在 C 语言中,使用 malloc 这种 "动态内存申请" 的函数,使用完之后,就需要手动调用 free 释放内存,如果不释放,就会出现内存泄露这样的问题,而在 Java 中就不用手动释放内存,因为 JVM 自动判定,是否某个对象已经不再使用了,并帮我们进行释放不再使用的对象的内存了。像这种不再使用的对象,就称之为 "垃圾",这种机制,也就叫做 GC 垃圾回收机制。
GC 也有缺陷:
1. 系统开销,需要有一个/一些特定的线程,不停的扫描你内存中的所有的对象,看是否能够回收,此时是需要额外的内存和 CPU 资源的。
2. 效率问题,这样的扫描线程,不一定能够及时的释放内存 (扫描总是有一定周期的),一旦同一时刻,出现大量的对象都需要被回收,GC 产生的负担就会很大,甚至引起整个程序都卡顿 (STW 问题 stop the world)
但是 GC 属于大势所趋,Python,PHP,Go.... 都是具有 GC 机制的。
GC 是垃圾回收,GC 回收的目标,其实是 内存中的 对象。
对于 Java 来说,就是 new 出来的这些对象。
栈里的局部变量,是跟随着栈帧的生命周期走的。(方法执行结束,栈帧销毁,内存自然释放)
静态变量,生命周期就是整个程序,这就意味着 静态变量 是无需释放的。
因此真正需要 gc 释放的对象就是 堆 上的对象。
gc 可以理解成两个大的步骤:
1. 找到垃圾
2. 释放垃圾
1) 找到垃圾
在 GC 的圈子中,有两种主流的方案:1. 引用计数 2. 可达性分析 (Java 采用的是这种)
a) 引用计数
new 出来的对象,单独安排一块空间,来保存一个计数器。
b) 可达性分析
可达性分析,本质上是一个时间换空间这样的手段。
有一个/一组线程,周期性的扫描代码中的所有对象。
从一些特定的对象出发,尽可能的进行访问的遍历,把所有能够访问到的对象,都标记成 "可达",反之,经过扫描之后,未被标记成 "可达" 的对象,就是垃圾了。
就跟二叉树的遍历差不多,只不过不是二叉树,而是 N 叉树。
2) 释放垃圾
有三种基本的思路:
1. 标记清除
是一种比较简单粗暴的方式。
2. 复制算法
第二种思路,就是解决,刚刚标记清除出现的内存碎片的办法。
通过复制的方式,把有效的对象,归类到一起,再统一释放剩下的空间。
3. 标记整理
既能够解决内存碎片的问题,又能够处理复制算法中利用率。
类似于顺序表删除元素的搬运操作。
实际上,JVM 采取的释放思路,是上述基础思路的结合体。
分代回收:
分代回收,对象能活过的 GC 扫描轮次越多,就是越老。
相关文章:

JVM 双亲委派模型以及垃圾回收机制
目录 1. JVM 内存区域划分 2. JVM 中类加载的过程 1) 类加载的基本流程 2) 双亲委派模型 3. JVM 中垃圾回收机制 1) 找到垃圾 a) 引用计数 b) 可达性分析 2) 释放垃圾 1. JVM 内存区域划分 一个运行起来的 Java 进程,其实就是一个 JVM 虚拟机。 而进程是…...
Delphi编写涂鸦桌面的小程序
用Delphi编写涂鸦桌面的小程序,类似于腾讯会议中的画板功能的实现。这里用Delphi实现代码给大家提供一些思路; 首先,新建一个Application,将Form1的WindowState设为wsMaximized,BorderStyle设为bsNone。这样做的目的就…...
智星云技术文档:GPU测速教程
安装gpu burn git clone https://github.com/wilicc/gpu-burn cd gpu-burn/ make测试 ./gpu_burn 60100.0% procd: 14280 (7373 Gflop/s) - 13390 (6997 Gflop/s) - 15912 (7110 Gflop/s) - 13184 (7055 Gflop/s) - 13464 (7369 Gflop/s) - 13974 (7351 Gflop/s) - 16626 (7…...
《Kali Linux 软件源更换攻略:优化软件获取与系统更新》
KALI为什么要换源 速度提升 Kali Linux 默认的软件源服务器通常位于国外。在从这些国外源下载软件包、更新系统时,会受到网络带宽、网络延迟等因素的限制。例如,在中国,连接到国外服务器的网络速度可能较慢,尤其是在下载大型软件…...
C# 在dataview可以直接增删改查mysql数据库
C# 在dataview可以直接增删改查mysql数据库 首先,确保你的项目中已经安装了MySql.Data。你可以通过NuGet包管理器安装它: Install-Package MySql.Data -Version 8.0.28using System; using System.Data; using MySql.Data.MySqlClient;public class My…...
C#—泛型约束
C#—泛型约束 概念: 泛型约束就是告知编译器类型参数必须具备的功能。 在没有任何约束的情况下,类型参数可以是任何类型。 编译器只能假定 System.Object 的成员,它是任何 .NET 类型的最终基类。当分配给泛型的类型参数不满足约束的类型时&…...
MeiliSearch:一款轻量级开源搜索引擎
Meilisearch 是由 Meili (一家总部位于法国的软件开发公司)创建的搜索引擎,目前在 Github 上有 47.9k stars。 Meillisearch 具备以下特色功能(ChatGPT-4o 翻译): 混合搜索:结合语义搜索和全文…...

Ansible playbook 详解与实战操作
一、概述 playbook 与 ad-hoc 相比,是一种完全不同的运用 ansible 的方式,类似与 saltstack 的 state 状态文件。ad-hoc 无法持久使用,playbook 可以持久使用。 playbook 是由一个或多个 play 组成的列表,play 的主要功能在于将事先归并为一…...

青少年夏令营管理系统的设计与开发(社团管理)(springboot+vue)+文档
💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...
加速合并,音频与字幕的探讨
因上一节。合并时速度太慢了。显卡没用上。所以想快一点。1分钟的视频用了5分钟。 在合并视频时,进度条中的 now=None 通常表示当前处理的时间点没有被正确记录或显示。这可能是由于 moviepy 的内部实现细节或配置问题。为了加快视频合并速度并利用 GPU 加速,可以采取以下措…...
Uniapp插件如何通过NFC读取多种证卡信息?
nfc读卡uniapp插件,由中软高科进行开发,主要是通过NFC读取居民身份证、港澳台居住证、外国人居住证、护照等证卡的信息。经过多个版本的升级更新,目前性能已趋于稳定,并且读卡速度较之最初版本有了大的提升。 注意事项 测试使用的…...
米哈游C++开发精选60道面试题及参考答案
C++ 面向对象的三个特征 封装是把数据和操作数据的函数捆绑在一起,并且对数据的访问进行限制。这样做的好处是可以隐藏对象的内部实现细节,只暴露必要的接口给外部。例如,在一个银行账户类中,账户余额这个数据成员是被封装起来的,外部不能直接访问和修改,而是通过存款、取…...
深度与视差的关系及其转换
深度与视差的关系及其转换 在计算机视觉和立体视觉中,深度和视差是两个重要的概念。理解这两者之间的关系对于实现立体图像处理、三维重建以及深度估计至关重要。在这篇博客中,我们将深入探讨深度和视差的概念,并介绍它们之间的转换关系。 …...
安全见闻全解析
跟随 泷羽sec团队学习 声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及…...

搭建Tomcat(四)---Servlet容器
目录 引入 Servlet容器 一、优化MyTomcat ①先将MyTomcat的main函数搬过来: ②将getClass()函数搬过来 ③创建容器 ④连接ServletConfigMapping和MyTomcat 连接: ⑤完整的ServletConfigMapping和MyTomcat方法: a.ServletConfigMappin…...

PT2044A 单触控单输出IC
1 产品概述 ● PT2044A 是一款单通道触摸检测芯片。该芯片内建稳压电路,提供稳定电压给触摸感应电路使用。同时内部集成高效完善的触摸检测算法,使得芯片具有稳定的触摸检测效果。该芯片专为取代传统按键而设计,具有宽工作电压与低功耗的特性…...

docker安装mysql5.7
1、宿主机创建映射目录 mkdir -p /data/mysql/log mkdir -p /data/mysql/data mkdir -p /data/mysql/conf这里我放在了/data/mysql目录下 2、拉取mysql镜像 docker pull mysql:5.7注意是5.7版本,如果是8版本操作会略有不同,下篇文章介绍安装8版本的操…...

安卓 文件管理相关功能记录
文件管理细分为图片、视频、音乐、文件四类 目录 权限 静态声明权限 动态检查和声明权限方法 如何开始上述动态申请的流程 提示 图片 获取图片文件的对象列表 展示 删除 视频 获取视频文件的对象列表 获取视频file列表 按日期装载视频文件列表 展示 播放 删除…...

GB28181系列三:GB28181流媒体服务器ZLMediaKit
我的音视频/流媒体开源项目(github) GB28181系列目录 目录 一、ZLMediaKit介绍 二、 ZLMediaKit安装、运行(Ubuntu) 1、安装 2、运行 3、配置 三、ZLMediaKit使用 一、ZLMediaKit介绍 ZLMediaKit是一个基于C11的高性能运营级流媒体服务框架,项目地址…...

ScottPlot学习的常用笔记
ScottPlot学习的常用笔记 写在前面版本的选择第一个障碍:版本问题。 ScottPlot4.0的官方网站与示例官方起始页cookbook5.0Demo4.1 demo以4.1为例,解压和运行如下: 下载源代码和编译先说结论: 写在前面 之前调研的TraceCompass&am…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...