JVM的垃圾回收

JVM简介

JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。
虚拟机:是指通过软件模拟的具有完整硬件功能、运行在一个完全隔离的环境中完整计算机系统

1.JVM的内存区域划分
jvm是一个java进程 每一个java进程就是一个jvm实例
一个进程运行过程中 就要从操作系统这里申请到一些内存资源 jvm也是如此 所以用一块内存供java代码执行时使用 jvm把这一块内存 有划分几个区域作为不同的用途
在这里插入图片描述
栈里面方法的调用关系 局部变量(使用的是递归调用)
栈空间和程序计数器 是每一个线程各有一份
每个线程 都是一个独立的执行逻辑 就能得到单独记录执行到哪里

下面有一段代码

class Test{public int n = 20;public static int a = 10;
}
public static void main(){Test t = new Test();
}

n是普通的成员变量 就是包含在new对象内部 堆上的
a是一个静态成员变量 是包含在类对象中方法区的
t是一个局部变量(引用类型) 栈上
这里栈上的t保存了堆上new Test()的内存地址

2.JVM类加载机制
把类从硬盘加载到内存中 java程序最开始就是写一个java文件编译成.class文件(字节码) 运行java程序JVM就会读取class文件 把文件内容 放到内存中并构成class对象

简单描述下类加载

  1. 加载找到class文件 打开文件 读取文件内容并尝试解析格式
    在java代码就是直接使用类
  2. 验证 检查当前.class文件格式 是否符合要求
    ,这一阶段的目的是确保Class文件的字节 流中包含的信息符合《Java虚拟机
    规范》的全部约束要求,保证这些信 息被当作代码运行后不会危害虚拟机自身的安全。
  3. 准备 给类对象分配内存
    最终目的是构造出完整的类对象 分配内存+初始化
    分配出来的内存空间 内容就是权威0的值(此时此刻 类对象上static成员也就是都是0)
  4. 解析 主要是初始化类对象中涉及到的一些字符串常量
  5. 初始化对类对象进行更具体的初始化操作初始化静态成员 执行静态代码块 加载父类

双亲委派模型(描述类加载过程中 如何找到.class文件)
JVM加载.class文件的时候需要用到"类加载器"模块
JVM中自带了三个类加载器
Bootstrap ClassLoader 负责加载标准库中的类
Extension ClassLoader 负责加载JVM扩展的库
Application ClassLoader 负责加载第三方库(mysql jdbc driver servlet jackson 等)

  1. 从Application ClassLoader开始
    不会立即就搜索第三方库的目录 而是先把加载任务委派给父亲 让父亲先尝试加载
  2. 到了Extension ClassLoader
    也不会立即搜索扩展库的目录 而是继续把任务派给父亲 让父亲先尝试加载
    3)再到Booststrap ClassLoader
    同样不会立即搜寻标准库 但是Bootstrap ClassLoadr没有父亲了就只能自己搜索 如果没找到这个类就会交给孩子完成 -> Extension ClassLoader
  3. 任务回到Extension ClassLoader
    如果找到了这个类 就进行后续加载
    如果没找到这个类就会交给孩子完成
    5)任务回到Application ClassLoader
    如果找到了类就进行后续加载
    如果没找到就会抛出一个异常

双亲委派模型 工作就是找.class文件 每个类加载器都有自己的"父亲"

一个类什么时候才会被加载?
类的加载使用的是懒汉模式 用到了才加载
分为以下三种情况

  1. 构造类的实例
  2. 使用了类的静态方法/静态属性
  3. 子类的加载会触发父类
    类加载之后 后续就不用加载了

类卸载 类的卸载
一般来说类卸载是属于特殊情况
类加载之后就不会考虑卸载 一直保持到程序运行结束
但有时我们服务器需要打 热补丁 需要卸载操作

3.JVM的垃圾回收机制(GC)
java的垃圾回收机制 会自动判定 某个内存是否会继续使用(如果不会 就会把内存当初垃圾 自动把垃圾释放掉)

垃圾回收 对于java来说 回收的是对象而不是字节(GC不是判定某个字节是不是垃圾而是判定对象是不是垃圾 进一步去进行回收的)

JVM中有几个内存区域 GC回收是回收的是那里的对象?
JVM的内存区域有栈 堆 方法区 栈空间不需要GC回收栈里面包含很多"栈帧"每一个栈帧对应一个方法 该方法执行结束 此时这个栈帧就销毁了 然后在栈上的局部变量就自然销毁了

程序计数器同理 线程销毁 也自然跟着销毁

方法区 类对象 很少会涉及对象的卸载

所以 堆 GC的主要战场

Java垃圾回收 分两步

  1. 判定对象是否是"垃圾"
    如果一个对象 在后续代码中不再被使用就可以看作是垃圾了 一个对象如果没有任何引用指用它就可以认为是垃圾(Java中要使用一个对象 只有一种途径 就是先创一个引用指向它 然后通过引用访问对象的属性/方法)
    例如:
public void test(){T t = new T();t.function();
}
test();

t是一个局部变量此时 test方法执行完毕之后 t 就自然销毁 此时 new T() 对象就没有引用了 此时 这个对象就是垃圾

判定对象是否是垃圾 就是看这个对象是否有引用指向它 那么如何看对象是否有引用指向它呢?

思路一: 引用计数
给这个对象里面安排一个计数器 每次有引用指向它 就把计数器加一 每次引用被销毁 计数器减一 当计数器为0 的时候就说明这个对象是垃圾了
例如:

class Test{int m;int n;
}
Test a = new Test();
Test b = a;
Test c = b;

对象中 会专门留一个空间来存储引用的个数
在这里插入图片描述

此处a这个引用指向Test
b指向引用a
c指向引用b
然后Test的就被引用了三次 所以计数器加三
在这里插入图片描述
然后我们将
a = null;
此时引用减少一次 计数器减一
在这里插入图片描述
当剩下两个引用都置为null时 这个对象就是垃圾了
在这里插入图片描述
这就是引用计数方案 但存在两个明显的缺陷

  1. 空间利用率比较低 浪费更多的内存空间
    如果给引用计数分配了2各字节 对象本体才4各字节 引用计数就浪费了50%的空间 代码中都是小对象 并且数量多时浪费就很明显了
  2. 可能存在循环引用的问题 且对象不能被正确识别为垃圾
    例如:
class Test{public Test t;
}
//第一步
Test a = new Test();
Test b = new Test();
//第二步
a.t = b;
b.t = a;
//第三步
a = null;
b = null;

第一步时
在这里插入图片描述

第二步时
在这里插入图片描述
第三步时
在这里插入图片描述
此时这两个对象计算器不为0 不能被当作垃圾 于此同时 想要使用对象1 就要访问 对象2 想使用对象2就要访问道对象1 谁都用不了 谁有无法释放和死锁非常相似

方案二: 可达性分析 (这是java中实际采取的方式)
JVM 首先会从现有代码中能直接访问到的引用出发尝试遍历所有能访问的对象 只要对象能访问到就会标记成可达 完成所有遍历之后 不能访问到的对象就是不可达 就相当于垃圾了

gc root(从那些对象开始出发扫描?)

  1. 栈上的局部变量
  2. 常量池的引用
  3. 方法区中的静态成员

例如:

在这里插入图片描述
这样一颗二叉树结构
root = a
root.left = b
root.left.left = d
以此类推可以通过a进行访问到后续任何一个节点
如果此时令root.left.left = null 此时d就会空无法通过root遍历d就是不可达得了 此时d引用的对象就会被垃圾回收

以上就是可达性分析 和引用计数不同的时它消耗的是时间 通过引用计数可以非常快的知道对象是否是垃圾但是会消耗大量的空间
而可达性分析不会引入额外的空间开销 但进行遍历需要消耗时间

可达性分析的扫描是持续的 周期性的

  1. 释放对象的内存
    那我们确定了垃圾 又该如何清理垃圾 释放对象呢?

(1) 标记清除
直接释放对象 但是可能引起内存碎片
在这里插入图片描述
这是因为申请内存的时候都是申请连续的内存空间
释放内存就可能会破坏原有的连续性 导致内存申请不了 如果不处理内存碎片会随着程序的运行越来越多 越来越碎内存就会变得很难申请了

(2) 复制算法
复制算法 通过冗余的空间 把有效对象复制到另一个部分空间 避免内存碎片

把一个内存 分成两份用一份 删除一份
把左侧区域中有效的对象复制到右侧
使用右侧区域使用一段时间后存在很多对象然后把有效的对象在复制到左侧然后把左侧的对象全部同意释放
例如:
假设对象2是垃圾对象然后把13复制到右边内存再释放掉左侧内存

在这里插入图片描述
在这里插入图片描述
这里如果复制的内容多 内存开销很大内存率不高

(3) 标记整理
顺序表删除元素
假设34是

在这里插入图片描述
把5对象往前移两个单位内存就相当于删除了

在这里插入图片描述
这一方法解决了内存利用率低的问题但是
搬运的元素成本比较高

(4) 分代回收
Java代码中 对象分成两个大类
1.生命周期特别长
2.生命周期特别短
所以可以按照对象的年龄来定制不同的回收策略
GC就是周期性扫描 一个对象每经历一轮GC就看作长了一岁
在这里插入图片描述

新生的对象就在伊甸区 这里的对象大部分无法活过第一轮GC 第一轮gc经过之后还剩下的对象 就会被通过复制算法复制到幸存区

幸存区继续使用复制算法 如果这个对象在幸存区经过了许多轮依旧没有清理掉 就进入了老年代了

新生代的扫描频率比较高
老年代的扫描频率比较低

新生代每一轮gc留下的有效对象不过 使用复制算法开销不大
老年代不会有频繁的对象销毁对此 使用标记整理开销不大

还有一个特殊情况如果对象体积特别大就会直接进入老年代

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

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

相关文章

VscodeC/C++环境配置

引言 vscode是一款非常好用的编辑器,集成了大量的插件,具有很高的自由度,因此广受大家的喜爱。但是他本身是不带编译器的,因此如果要使用vscode来编译C/C程序的话,我们需要额外安装编译器并且为vscode配上环境。 编译…

一文教会你lambda表达式

引言 在现代编程中,Lambda表达式(也称为匿名函数或闭包)已经成为了一种非常流行的编程范式。它允许我们定义简短、一次性的函数对象,而无需显式地定义它们。在C11及之后的版本中,Lambda表达式得到了官方的支持&#x…

梦幻西游12门派复古怀旧 单机版 安装简单,云盘下载哦

做游戏开发的朋友,可以多参考里面的设计思想,真的不错。 梦幻西游12门派复古怀旧 单机版 安装简单,云盘下载哦 游戏大小: 支持系统:win7、win10 64位 特色:简化安装,非常容易。 重新整盒高…

Ubuntu下halcon软件的下载安装

由于工作需求,点云配准需要使用halcon进行实现,并且将该功能放入QT界面中 1.下载halcon 进入halcon官网进行下载 官网链接:https://www.mvtec.com/products/halcon/ 注意:要注册登陆之后才能进行下载 接着点击Downloads->H…

MouseBoost PRO mac中文激活版:专业鼠标助手

MouseBoost PRO mac鼠标性能优化软件,以其强大的功能和智能化的操作,助您轻松驾驭鼠标,提高工作效率。 MouseBoost PRO支持自定义快捷键设置,让您轻松实现快速切换应用程序、打开特定文件、调节音量大小等操作。自动识别窗口功能则…

240多道!Go开发岗位面试题合集(含答案)

随着今年互联网寒潮环境的影响,找工作的人也将达到顶峰,今天给大家分享一份《Go开发工程师超高频面试真题》,一共有240多道面试真题,希望能够帮助大家在面试中,少走一些弯路、更快拿到offer! 内容展示 GO 基…

Dreamweaver 2021 for Mac 激活版:网页设计工具

在追求卓越的网页设计道路上,Dreamweaver 2021 for Mac无疑是您的梦幻之选。这款专为Mac用户打造的网页设计工具,集强大的功能与出色的用户体验于一身。 Dreamweaver 2021支持多种网页标准和技术,让您能够轻松创建符合现代网页设计的作品。其…

[Algorithm][BFS][拓扑排序][课程表][课程表Ⅱ][火星词典] + BFS解决拓扑排序原理 详细讲解

目录 0.原理讲解1.有向无环图2.AOV网3.拓扑排序4.实现拓扑排序5.如何建图? 1.课程表1.题目链接2.算法原理详解3.代码实现 2.课程表 II1.题目链接2.算法原理详解3.代码实现 3.火星词典1.题目链接2.算法原理详解3.代码实现 0.原理讲解 1.有向无环图 有向无环图&#…

基于Django图像识别系统毕业设计(付源码)

前言:Django是一个由Python编写的具有完整架站能力的开源Web框架,Django本身基于MVC模型,即Model(模型)View(视图) Controller(控制器)设计模式,因此天然具有…

【抽样调查】分层抽样上

碎碎念:在大一大二时听课有的时候会发现听不太懂,那时候只觉得是我自己的基础不好的原因,但现在我发现“听不懂”是能够针对性解决的。比如抽样调查这门课,分析过后我发现我听不懂的原因之一是“没有框架”,一大堆知识…

【使用ChatGPT的API之前】OpenAI API提供的可用模型

文章目录 一. ChatGPT基本概念二. OpenAI API提供的可用模型1. InstructGPT2. ChatGPT3. GPT-4 三. 在OpenAI Playground中使用GPT模型-ing 在使用GPT-4和ChatGPT的API集成到Python应用程序之前,我们先了解ChatGPT的基本概念,与OpenAI API提供的可用模型…

情感分类学习笔记(1)

文本情感分类(二):深度学习模型 - 科学空间|Scientific Spaces 一、代码理解 cw lambda x: list(jieba.cut(x)) #定义分词函数 您给出的代码定义了一个使用 jieba 分词库的分词函数。jieba 是一个用于中文分词的 Python 库。该函数 cw 是…

FTTR介绍

概念 FTTR(Fiber to The Room)是一种新型的光纤接入技术,它将光纤信号传输到室内的一个通信网络方案。在FTTR网络中,光纤到达建筑物内的分配盒后,通过铜缆或其他传输介质进入室内各个房间,为用户提供网络服…

Java面试八股文(SpringCloud篇)

****************************************************

前端双语实现方案(VUE版)

一、封装一个lib包 结构如下 en.js use strict;exports.__esModule true; exports.default {sp: {input: {amountError: Incorrect amount format},table: {total: Total:,selected: Selected:,tableNoData: No data,tableNoDataSubtext: Tip: Suggest to recheck your fil…

使用css的box-reflect属性制作倒影效果

box-reflect 是一个在 CSS 中创建元素倒影效果的非标准属性。尽管它在过去的一些 WebKit 浏览器中(如旧版的 Safari 和 Chrome)得到了支持,但由于它并未成为 CSS 标准的一部分,因此在现代浏览器中的兼容性较差。以下是对 box-refl…

瑞麦德机电设备有限公司将莅临2024第13届生物发酵展

参展企业介绍 河南瑞麦德机电设备有限公司是专业从事机械输送气力输送、称重配料、筛分、磁选设备研发和制造于一体的企业,公司采用国内外同行业产品的先进技术,经专业团队设计、研发、生产,产品满足“ISO9001”,“GMP”等标准要求…

【BST】Behavior Sequence Transformer for E-commerceRecommendation in Alibaba

一、提出背景 传统的Embedding&MLP模型结构将原始特征嵌入到低维向量中,然后将其concat后输入MLP进行最终推荐。DIN提出使用注意力机制来捕获候选项与用户先前点击的项之间的相似性。 然而,大多数这些工作只是连接不同的特征,而没有捕获用…

云动态摘要 2024-05-08

给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。 最新优惠与活动 [免费试用]即刻畅享自研SaaS产品 腾讯云 2024-04-25 涵盖办公协同、营销拓客、上云安全保障、数据分析处理等多场景 云服务器ECS试用产品续用 阿里云 2024-04-14 云服务器ECS试用产品续用…

通过自适应提示提升大语言模型的零样本推理能力

随着大模型(LLMs)的快速发展,它们在自然语言处理(NLP)任务上取得了前所未有的成就。特别是,LLMs展现出了强大的推理和规划能力,这得益于它们的少样本和零样本学习能力。然而,现有的方…