JVM(内存划分,类加载,垃圾回收)
JVM
Java程序,是一个名字为Java 的进程,这个进程就是所说的“JVM”
1.内存区域划分
JVM会先从操作系统这里申请一块内存空间,在这个基础上再把这个内存空间划分为几个小的区域
在一个JVM进程中,堆和方法区只有一份;栈和程序计数器,每个线程有一份

1.堆:存放new的对象
堆里面分为两个区域:新生代和老年代,新生代放新建的对象,当经过一定GC次数之后还存活的对象会放入老年代。新生代还有三个区域:一个 Endn + 两个 Survivor(S0/S1)

垃圾回收的时候会将 Endn 中存货的对象放到一个未使用的Survivor 中,并把当前的 Endn 和正在使用的 Survivior 清除掉
2.栈:存放方法之间的调度关系
虚拟机栈:java里面用来保存调用关系的内存空间
本地方法栈:本地方法,就是JVM内部 C++ 写的代码,调用关系的内存空间
3.程序计数器:存放下一个要执行的指令的地址
程序计数器是一块比较小的内存空间,可以看作释放前线程所执行的字节码的行号指示器
4.方法区:存放类对象(加载好的)
方法区的作用:用来存储被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据的
变量在哪个部分和变量类型无关,和变量的形态有关(成员,静态,局部)
代码里的局部变量:栈
代码里的成员变量:堆
代码里的静态变量:方法区
2.类加载
java程序在运行之前,需要先编译 .java => .class(二进制字节码文件)运行的时候,Java 进程(JVM)就会读取对应的 .class 文件,并且解析内容,在内存中构造出类对象并进行初始化
1.类加载过程

其中前5步时固定的顺序,并且也是类加载的过程,其中中间的3步都属于连接,所以类加载总共分为现在几个步骤
加载:找到.class文件,读取文件内容,并且按照.class规范格式来解析
验证:检查看当前的.class里的内容格式是否符合要求
准备:给类里的静态变量分配内存空间
解析:初始化字符串常量,把符号引用替换成直接引用(在类加载之前,字符串常量是没有分配内存空间的,变量名称无法保存字符串常量的真实地址,只能先使用一个占位符,等类加载完成,字符串常量分配过内存之后,就可以用真正的地址替换占位符)
初始化:针对类进行初始化,初始化静态成员,执行静态代码块,并且加载父类
2.何时触发类加载
使用到一个类的时候,就触发加载(类并不一定是程序一启动就加载了,而是第一次使用才加载)
创建这个类的实例
使用了这个类的静态方法/静态属性
使用类的子类(加载子类就会触发加载父类)
3.双亲委派模型
如果一个类加载器收到了类加载的请求,它首先不会自己尝试去加载,而是将这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去完成加载
类加载器:JVM加载类,是由类加载器(class loader)模块来负责的
JVM 自带了多个类加载器:
Bootstrap ClassLoader 负责加载标准库中的类
Extension ClassLoader 负责加载 JVM 扩展的库的类
Application ClassLoader 负责加载自己的项目里的自定义类
双亲委派模型的工作过程:

上述三个类加载器存在父子关系
进行类加载的时候,输入的内容全限定类名,形如:java.lang.Thread
加载的时候,从Application ClassLoader开始
某个类加载器开始加载到时候,不会立即扫描自己的路径,而是先把任务委派给父“类加载器”
找到最上面的 Bootstrap ClassLoader在往上,没有父“类加载器”了,就会自己加载
如果父”类加载器“没有找到类,就会交给自己的子”类加载器“,继续加载
如果一直找到最下面的Application ClassLoader 也没有找到类,就会抛出一个“类没找到”异常,类加载就失败了
3.垃圾回收(GC)
Java堆中存放着几乎所有的对象实例,垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象哪些还被引用着,哪些已经没有引用了。判断对象是否被引用有如下几种算法:
内存VS对象
在Java中,所有的对象都是要存在内存中的,因此将内存回收也叫做死亡对象的回收。
1.GC回收的部分
JVM主要内存分成这几个部分:
堆:GC主要针对堆来回收
方法区:类对象,加载之后也不太会卸载
栈:释放时机确定,不必回收
程序计数器:固定内存空间,不必回收

2.回收对象的判断算法
1.引用计数算法
给每个对象都加上一个计数器,这个计数器就表示“当前的对象几个引用”
但是,主流的 JVM 中没有选用引用计数法来管理内存,最主要的原因就是引用计数法无法解决对象循环引用问题
循环引用:
当两个对象互相引用时
classTest{
Testx;
}
Testa=newTest();
Testb=newTest();
a.x=b;
b.x=a;
a=null;
b=null;
当前这两个对象的计数器都为1,所以无法进行释放,此时外界的代码仍然时无法访问和使用对象的
2.可达性分析【JVM采取的方法】
核心思想:通过一系列称为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称之为 “引用链”,当一个对象到GC Roots没有任何的引用链时,证明此对象是不可用的

对象 Object 5-Object 7 之间虽然还有关联,但是它们到达不了GC Roots 是不可达的,因此他们会被判定为可回收对象
在Java语言中,课作为GC Roots的对象包含下面几种:
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中JNI(Native)引用的对象
3.垃圾回收算法
1.标记-清除算法
首先标记出垃圾,然后直接把对象对应的内存空间进行释放

标记-清楚算法的不足:
效率问题:标记和清楚这两个过程的效率都不高
空间问题:标记清楚后会产生大量不连续的内存碎片,内存碎片较多会导致在分配内存空间较大的对象时,无法找到足够连续的内存
2.复制算法
复制算法是为了解决“标记-清楚”算法带来的问题描述:将一个内存空间分为两部分,首先先使用一边,清理时不再是原地释放,而是把“非垃圾”拷贝了另一边,然后再把之前这一边给释放掉

复制算法的不足:
空间利用率更低了(一次只能使用一半的内存空间)
如果一轮GC下来,大部分对象仍然需要保留,只有少数对象要回收,这个时候拷贝开销就很大
3.标记-整理算法
前面与“标记-清理”算法过程一致,打包后续不是直接堆可回收对象进行清理,而是让所有存活对象都想一段移动,然后直接清理掉边界以外的内存(类似于顺序表的删除元素操作)

这种方式,相对于上述的复制算法来说,空间利用率上来了,同时能够解决内存碎片问题,但是搬运操作也是比较耗时的
4.分代回收算法
分代算法是通过区域划分,实现不同区域和不同的垃圾回收策略,从而实现更好的垃圾回收(当前 JVM 垃圾收集采用此算法)一般是将Java堆分为新生代(GC 扫描的频率更高)和老年代(GC 扫描的频率降低),在新生代中,每次垃圾回收都有大批对象死去,只有少量存活,因此我们采用复制算法;而老年代中对象存活率高,没有额外空间对它进行分配担保,就必须采用“标记-清除”或者“标记-整理”算法
根据对象的不同特点(根据对象的年龄(依据 GC 的轮次来算的,有一组线程,周期性的扫描代码里所有的对象,如果一个对象,经历了一次GC ,就认为年龄+1)来划分)。
一个基本的经验规律:如果一个对象的寿命比较长,大概率还会活很久

上述规则还有个特殊情况,如果对象是一个非常大的对象,将会直接进入老年代!
相关文章:
JVM(内存划分,类加载,垃圾回收)
JVMJava程序,是一个名字为Java 的进程,这个进程就是所说的“JVM”1.内存区域划分JVM会先从操作系统这里申请一块内存空间,在这个基础上再把这个内存空间划分为几个小的区域在一个JVM进程中,堆和方法区只有一份;栈和程序…...
工作中遇到的问题 -- 你见过哪些写的特别好的代码
strPtr : uintptr((*(*stringStruct)(unsafe.Pointer(&str))).str)代码解析: 这是一段 Go 代码,它的作用是获取一个字符串变量 str 的底层指针,即字符串数据的起始地址。 这段代码涉及到了 Go 语言中的指针、类型转换和内存布局等概念&…...
基于chatGPT设计卷积神经网络
1. 简介 本文主要介绍基于chatGPT,设计一个针对骁龙855芯片设计的友好型神经网络。 提问->跑通总共花了5min左右,最终得到的网络在Cifar100数据集上与ResNet18的精度对比如下。 模型flopsparamstrain acc1/5test acc1/5ResNet18(timm)1.8211.18~98…...
java.sql.Date和java.util.Date的区别
参考答案 java.sql.Date 是 java.util.Date 的子类java.util.Date 是 JDK 中的日期类,精确到时、分、秒、毫秒java.sql.Date 与数据库 Date 相对应的一个类型,只有日期部分,时分秒都会设置为 0,如:2019-10-23 00:00:0…...
动态规划---线性dp和区间dp
动态规划(三) 目录动态规划(三)一:线性DP1.数字三角形1.1数字三角形题目1.2代码思路1.3代码实现(正序and倒序)2.最长上升子序列2.1最长上升子序列题目2.2代码思路2.3代码实现3.最长公共子序列3.1最长公共子序列题目3.2代码思路3.3代码实现4.石子合并4.1题目如下4.2代…...
常见的2D与3D碰撞检测算法
分离轴分离轴定理(Separating Axis Theorem)是用于解决2D或3D物体碰撞检测问题的一种方法。其基本思想是,如果两个物体未发生碰撞,那么可以找到一条分离轴(即一条直线或平面),两个物体在该轴上的…...
STM32 10个工程篇:1.IAP远程升级(二)
一直提醒自己要更新CSDN博客,但是确实这段时间到了一个项目的关键节点,杂七杂八的事情突然就一涌而至。STM32、FPGA下位机代码和对应Labview的IAP升级助手、波形设置助手上位机代码笔者已经调试通过,因为不想去水博客、凑数量,复制…...
Unity+ChatGpt的联动 AICommand
果然爱是会消失的,对吗 chatGpt没出现之前起码还看人家的文章,现在都是随便你。 本着师夷长技以制夷的思路,既然打不过,那么我就加入 github地址:https://github.com/keijiro/AICommand 文档用chatGpt翻译如下&#…...
STM-32:按键控制LED灯 程序详解
目录一、基本原理二、接线图三、程序思路3.1库函数3.2程序代码注:一、基本原理 左边是STM322里电路每一个端口均可以配置的电路部分,右边部分是外接设备 电路图。 配置为 上拉输入模式的意思就是,VDD开关闭合,VSS开关断开。 浮空…...
北邮22信通:(8)实验1 题目五:大整数加减法(搬运官方代码)
北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 上一篇文章: 北邮22信通:(7)实验1 题目四:一元多项式(节省内存版)_青山如…...
Fiddler抓取https史上最强教程
有任何疑问建议观看下面视频 2023最新Fiddler抓包工具实战,2小时精通十年技术!!!对于想抓取HTTPS的测试初学者来说,常用的工具就是fiddler。 但是初学时,大家对于fiddler如何抓取HTTPS难免走歪路ÿ…...
STM32开发基础知识入门
C语言基础 位操作 对基本类型变量可以在位级别进行操作。 1) 不改变其他位的值的状况下,对某几个位进行设值。 先对需要设置的位用&操作符进行清零操作,然后用|操作符设值。 2) 移位操作提高代码的可读性。 3) ~取反操作使用技巧 可用于对某…...
学习操作系统的必备教科书《操作系统:原理与实现》| 文末赠书4本
使用了6年的实时操作系统,是时候梳理一下它的知识点了 摘要: 本文简单介绍了博主学习操作系统的心路历程,同时还给大家总结了一下当下流行的几种实时操作系统,以及在工程中OSAL应该如何设计。希望对大家有所启发和帮助。 文章目录…...
大数据的常用算法(分类、回归分析、聚类、关联规则、神经网络方法、web数据挖掘)
在大数据时代,数据挖掘是最关键的工作。大数据的挖掘是从海量、不完全的、有噪声的、模糊的、随机的大型数据库中发现隐含在其中有价值的、潜在有用的信息和知识的过程,也是一种决策支持过程。其主要基于人工智能,机器学习,模式学…...
【数据结构】详解二叉树与堆与堆排序的关系
🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 🚀数据结构专栏ÿ…...
【Pandas】数据分析入门
文章目录前言一、Pandas简介1.1 什么是Pandas1.2 Pandas应用二、Series结构2.1 Series简介2.2 基本使用三、DataFrame结构3.1 DataFrame简介3.2 基本使用四、Pandas-CSV4.1 CSV简介4.2 读取CSV文件4.3 数据处理五、数据清洗5.1 数据清洗的方法5.2 清洗案例总结前言 大家好&…...
【c++】:list模拟实现“任意位置插入删除我最强ƪ(˘⌣˘)ʃ“
文章目录 前言一.list的基本功能的使用二.list的模拟实现总结前言 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中࿰…...
QT表格控件实例(Table Widget 、Table View)
欢迎小伙伴的点评✨✨,相互学习🚀🚀🚀 博主🧑🧑 本着开源的精神交流Qt开发的经验、将持续更新续章,为社区贡献博主自身的开源精神👩🚀 文章目录前言一、图示实例二、列…...
第二章Vue组件化编程
文章目录模块与组件、模块化与组件化模块组件模块化组件化Vue中的组件含义非单文件组件基本使用组件注意事项使用 kebab-case使用 PascalCase组件的嵌套模板templateVueComponent一个重要的内置功能单文件组件Vue脚手架使用Vue CLI脚手架先配置环境初始化脚手架分析脚手架结构实…...
面试官:vue2和vue3的区别有哪些
目录 多根节点,fragment(碎片) Composition API reactive 函数是用来创建响应式对象 Ref toRef toRefs 去除了管道 v-model的prop 和 event 默认名称会更改 vue2写法 Vue 3写法 vue3组件需要使用v-model时的写法 其他语法 1. 创…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
