当前位置: 首页 > news >正文

浅谈 JVM

JVM 内存划分

JVM 内存划分为 四个区域,分别为 程序计数器、元数据区、栈、堆

程序计数器是记录当前指令执行到哪个地址

元数据区存储存储的是当前类加载好的数据,包括常量池和类对象的信息,.java 编译之后产生 .class 文件,运行代码的时候会把了类对象的信息保存在内存里,其中类元信息包括:类名、类的父类,实现哪些接口,类的权限public/private…
方法元信息:方法名,参数类型,返回值…
类元信息和方法元信息都是类对象里面包含的。

栈:分为本地方法栈和虚拟机栈,本质上都是存储方法的栈帧,每次调用方法的时候,会进行压栈,方法调用完会执行出栈操作,本地方法栈执行的是C++方法,虚拟机栈执行的是 Java方法。

堆:存放 new 出来的对象的实例。
Test t = new Test();
new Test() 这个对象的实例一定是存储在堆上的

t 需要分类讨论,如果 t 是一个局部变量,t 就是在栈上的;如果 t 是 成员变量,t 就是在堆上的;如果 t 是 静态成员变量,t 就是在元数据区里的。

在这里插入图片描述

元数据区 和 堆,整个Java进程共用一份
程序计数器和栈,每个线程有一份

在面试时,如果遇到谈一下栈和堆的话, 要注意是数据结构里的栈和堆, 还是JVM的栈和堆

类加载

1)加载:根据类的全限定名(包名+类名)找到对应的 .class 文件,然后打开文件,将文件的内容读取到内存中里。
2)验证:解析和校验 .class 文件的内容是否合法,如果合法就把这里的内容转化成结构化的数据
3)准备:给类对象申请 全0 的内存空间
4)解析:针对字符串常量进行初始化,将 .class 文件中的字符串常量放入元数据区的常量池中
5)初始化:将类对象进行最终的初始化,包括对类对象各种属性的填充,类中的静态成员,父类,如果父类没有被加载过,会触发父类的类加载。

类加载触发的时机为懒加载,当Java代码需要用到哪个类才会触发哪个类的加载

双亲委派模型

双亲委派模型的根据JVM实现类加载的源码提出的,也就是说是先有JVM的类加载源码,才有后面的双亲委派模型。

JVM 默认提供了三种类加载器,分别为 BootstrapClassLoader、ExtensionClassLoader、ApplicationClassLoader

你可以认为这三个类加载器的关系如下:
在这里插入图片描述
它们之间的联系,你可以认为是这三个类加载器都有一个引用指向上一个类加载器,ApplationClassLoader 的父亲的 ExtensionClassLoader,ExtensionClassLoader 的父亲是 BootstrapClassLoader,BootstrapClassLoader 的父亲为 null。

BootstrapClassLoader 负责加载Java 标准库的 .class 文件
ExtensionClassLoader 负责加载 Java 扩展库的 .class 文件
ApplicationClassLoader 负责加载 Java第三方库的.class 文件

随着时代的发展,Java的扩展库我们很少使用,取而代之的是Java第三方库,例如使用maven 加载的库就是第三方库

双亲委派模型的执行流程
进行类加载,通过全限定类名寻找 .class 文件,先从 ApplicationClassLoader 最为入口开始,然后将类加载任务委托上一级 ExtensionClassLoader ,再将类加载任务委托给上一级 BootstrapClassLoader,由于 BootstrapClsssLoader 没有上一级,开始执行类加载任务,将需要的Java标准库里的 .class 文件加载到内存里,然后将任务下放给下一级 ExtensionClassLoader ,ExtensionClassLoader 将所需要的Java扩展库的 .class 文件加载到内存里,最后将任务交给下一级 ApplicationClassLoader,ApplicationClassLoader 负责加载Java第三方库的 .class 文件。

如果没有找到对应的 .class 文件,就会抛出异常 ClassNotFoundException

在这里插入图片描述

垃圾回收 GC

在Java中你不需要手动释放内存,这是因为JVM 内部实现了 GC,也就是垃圾回收机制,这个机制可以自动回收内存空间,这使得Java程序员不需要考虑内存泄漏的问题。

垃圾回收有两个步骤:首先就是找到垃圾,然后再回收垃圾

如何找到垃圾???

找到垃圾这里介绍两个算法,一个是引用计数,另一个是可达性分析

引用计数

在创建的对象旁边开辟一个空间,用来存放该对象被多少个引用引用着,当被引用的数量为 0 的时候就会进行垃圾回收:

在这里插入图片描述

但这也有缺点:
1)内存消耗多,尤其是对象本身比较小的时候,引用计数占据的空间的比例就会很大,例如:假设对象自身占8个字节,引用计数可能占 4 个字节

2)可能出现 “ 循环引用” 的问题
假设一个类里面还定义了一个引用,用这个类创建的两个对象的引用相互指向对方,那这两个对象是不可能被垃圾回收掉的:
在这里插入图片描述
当我们将 a 和 b 两个引用置为 null 的时候,我们创建的两个对象的实例是不会被回收掉的,因为此时两个对象都被对方引用着,双方的引用计数均为 1,这就是 “循环引用”

可达性分析(JVM 使用)

为了解决上述引用计数产生的两个弊端(空间浪费和循环引用),这里提出了可达性分析算法。

可达性分析算法采用时间换空间的策略,这也是 JVM 寻找垃圾使用的算法

首先对代码的一些特定对象作为遍历的 “起点”:这些特定的对象包括 栈上的局部变量(引用变量)、常量池引用指向的对象、静态成员(引用类型的)【这些对象在程序运行到任何时刻都容易被捕获到的】
【因为不会扫描堆上的对象,所以不会存在因为 “循环引用” 而影响垃圾判断的现象】

然后进行遍历:判断某个对象是否能被访问到,在能访问到的对象标记为 “可达”。

当完成遍历后,把未标记为 “可达” 的对象标记为 “不可达”

JVM 通过上述操作,就知道哪些对象是 可达的,哪些是 不可达的,接下来就是回收垃圾的操作了。

举个例子:

class Node {Node left;Node right;
}public class Test2 {public Node build() {Node a = new Node();Node b = new Node();Node c = new Node();Node d = new Node();Node e = new Node();Node f = new Node();Node g = new Node();a.left = b;a.right = c;b.left = d;b.right = e;f.right = g;return a;}
}

在这里插入图片描述
由于方法最后只返回 a 这个节点,这时候 f 和 g 节点就会被回收掉。

如何处理找到的垃圾???

这里介绍四种处理方式:标记–清除 算法,复制算法,标记整理 算法,分代算法,其中最后一个算法 分代算法是 JVM 真正使用的。

标记–清除 算法

在需要回收的内存上做上标记,然后进行回收清除操作,这是最直接的算法,但是存在一个缺点就是会产生内存碎片。

举个例子:假设一共有 7 块内存块,经过可行性分析算法得出 2、4、6 这三块内存为需要回收的内存,先做上标记,然后进行回收释放,但是空出来的内存碎片可能难以得到利用。
在这里插入图片描述

标记整理算法

由于标记清除算法会产生大量的内存碎片标记整理算法直接将垃圾回收设计为类似顺序表删除的形式, 将非垃圾的对象排到一起, 这样就可以空出大块的空闲内存块了.

但是缺点也是显而易见的, 就是系统开销比较大, 尤其是移动较大的对象的时候.
在这里插入图片描述

复制算法

将内存空间一分为二,当需要进行垃圾回收的时候,将非垃圾的内存块依次紧凑地复制到另一半内存中。

但是也存在两个缺点
1)内存消耗大,内存的空间利用率低
2)一旦非垃圾的内存块较多的时候,复制的成本就会较高,尤其是复制包含较大的对象的时候。

举个例子:要回收 1 和 4 号内存块。
在这里插入图片描述

分代算法 (JVM 使用)

分代算法是结合了上面两种算法的优点,取长补短的综合算法

JVM 将对象划分为 新生代和老年代,新生代又划分了三个区域分别是伊甸区、两个幸存区【空间占比为8:1:1】

分代算法的代指的是对象的年龄大小, 年龄的大小和 GC 轮次相关

在这里插入图片描述

命名的来源于圣经,人类发源地伊甸园,在这里指新生成的对象的存放位置,由于灭世洪水的降临,人类打造了诺亚方舟,成功躲避天灾的人门就是幸存者,这里的幸存区是指对象经过GC之后还能存留下来的存储位置

我们认为对象一开始生成的时候,是最容易被 GC 掉的,所以新生成的对象保存在 伊甸区里,经过 一轮GC 之后剩下的对象不会很多,将这些幸存的对象放到幸存区里,两个幸存区就是为了执行复制算法,经过多轮 GC 之后,还能在幸存区里存活的对象将放入到老年代。

一般来说,如果内存占用空间比较大的对象我们一般是直接放入老年代, 减少系统开销

新生代的 GC 频次较高
老年代的 GC 频次较低

因为我们认为要 GC 掉的早就 GC 掉了,之所以能存活在老年代,说明这个对象经常被使用,也就是说老年代的对象不需要高频次的 GC 次数,GC 的周期可以长一点,减少系统开销。

相关文章:

浅谈 JVM

JVM 内存划分 JVM 内存划分为 四个区域,分别为 程序计数器、元数据区、栈、堆 程序计数器是记录当前指令执行到哪个地址 元数据区存储存储的是当前类加载好的数据,包括常量池和类对象的信息,.java 编译之后产生 .class 文件,运…...

html的iframe页面给帆软BI发送消息

需求&#xff1a;帆软的网页组件嵌套一个HTML页面&#xff0c;HTML页面要给帆软发消息。 解决方法是&#xff1a;fineReportWindow.duchamp.getWidgetByName("txt1").setValue(666); <!DOCTYPE html> <html lang"en"> <head> <…...

spark任务优化参数整理

以下参数中有sql字眼的一般只有spark-sql模块生效&#xff0c;如果你看过spark的源码&#xff0c;你会发现sql模块是在core模块上硬生生干了一层&#xff0c;所以反过来spark-sql可以复用core模块的配置&#xff0c;例外的时候会另行说明&#xff0c;此外由于总结这些参数是在不…...

C++ 模拟真人鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…...

生产环境中常用的设计模式

生产环境中常用的设计模式 设计模式目的使用场景示例单例模式保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点- 日志记录器- 配置管理器工厂方法模式定义一个创建对象的接口&#xff0c;让子类决定实例化哪个类- 各种工厂类&#xff08;如视频游戏工厂模式创…...

基于SpringBoot+Vue的药品管理系统【源码+文档+部署讲解】

系统介绍 基于SpringBootVue实现的药品管理系统采用前后端分离的架构方式&#xff0c;系统实现了用户登录、数据中心、药库管理、药房管理、物资管理、挂号管理、系统管理、基础设置等功能模块。 技术选型 开发工具&#xff1a;idea2020.3Webstorm2020.3 运行环境&#xff…...

【CompletableFuture实战】

CompletableFuture实战 前言 前言 过去的一年&#xff0c;匆匆忙忙&#xff0c;换了一次工作&#xff0c;写博客的习惯就落下了&#xff0c;总之&#xff0c;有点懈怠。希望今年能重拾信心&#xff0c;步入正规&#xff01; CompletableFuture的用法网上资料颇多&#xff0c;…...

Redis 缓存穿透、击穿、雪崩 的区别与解决方案

前言 Redis 是一个高性能的键值数据库&#xff0c;广泛应用于缓存、会话存储、实时数据分析等场景。然而&#xff0c;在高并发的环境下&#xff0c;Redis 缓存可能会遇到 缓存击穿、缓存穿透 和 缓存雪崩 这三大问题。这些问题不仅影响系统的稳定性和性能&#xff0c;还经常出…...

Python自动化测试中定位隐藏菜单元素的策略

大家都读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 在进行Python自动化测试时&#xff0c;尤其是使用Selenium等工具对Web应用进行测试时&#xff0c;可能会遇到某些元素被隐藏的问题。这使得元素定位和交互变得复杂。然而&#xff0c;通过一些技术手段…...

【张雪峰高考志愿填报】合集

【张雪峰高考志愿填报】合集 链接&#xff1a;https://pan.quark.cn/s/89a2d88fa807 高考结束&#xff0c;分数即将揭晓&#xff0c;志愿填报的关键时刻近在眼前&#xff01;同学们&#xff0c;这可是人生的重要转折点&#xff0c;选对志愿&#xff0c;就像为未来铺就一条…...

53,【3】BUUCTF WEB october 2019 Twice SQLinjection

题目得到信息&#xff0c;2次注入&#xff0c;进入靶场 登录页面&#xff0c;很自然想到SQL 第一次注入应该是这个可以登录&#xff0c;注册&#xff0c;提交简介的页面 第二次注入应该是在info处注入&#xff0c;信息显示在简介处 我真的纯脑子有病&#xff0c;人家二次注入不…...

【Linux系统】分区挂载

我们能够根据一个 inode 号在指定分区寻找目标文件的 struct inode&#xff0c;也能根据目录文件的内容&#xff0c;通过映射关系&#xff0c;找指定的 inode&#xff0c;可是&#xff0c;现在有个问题&#xff1a; 问题&#xff1a;inode 是不能跨分区使用的&#xff01;Linu…...

Oracle 可观测最佳实践

简介 Oracle 数据库是一种广泛使用的商业关系数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;由甲骨文公司&#xff08;Oracle Corporation&#xff09;开发。它支持 SQL 语言&#xff0c;能够存储和管理大量数据&#xff0c;并提供高级数据管理功能&#xff0c;如数…...

Ubuntu本地部署网站

目录 1.介绍 2.安装apache 3.网页升级 1.介绍 网站其实就相当于一个文件夹&#xff0c;用域名访问一个网页&#xff0c;就相当于访问了一台电脑的某一个文件夹&#xff0c;在网页中看见的视频&#xff0c;视频和音乐其实就是文件夹里面的文件。为什么网页看起来不像电脑文件夹…...

图数据库 | 18、高可用分布式设计(中)

上文我们聊了在设计高性能、高可用图数据库的时候&#xff0c;从单实例、单节点出发&#xff0c;一般有3种架构演进选项&#xff1a;主备高可用&#xff0c;今天我们具体讲讲分布式共识&#xff0c;以及大规模水平分布式。 主备高可用、分布式共识、大规模水平分布式&#xff…...

Java 读取 Windows 设备的唯一性标识及定位

在 Windows 系统中&#xff0c;获取设备唯一性标识及定位信息对设备管理、安全监控等场景意义重大。本文介绍 Java 中几种实现方法&#xff0c;如 JNA 库、WMI4Java 库及通过 JNI 结合 Windows API。 1. 使用 JNA 库读取 DEVPKEY_Device_ContainerId 在 Windows 系统中&…...

Spring boot框架下的RabbitMQ消息中间件

1. RabbitMQ 基础概念 1.1 消息处理流程与组件配合 Producer&#xff08;生产者&#xff09; 发送消息。消息先发送到 Exchange&#xff08;交换机&#xff09;&#xff0c;而不是直接到队列。Exchange&#xff08;交换机&#xff09; 接收到消息后&#xff0c;根据 Routing …...

1 行命令引发的 Go 应用崩溃

一、前言 不久前&#xff0c;阿里云 ARMS 团队、编译器团队、MSE 团队携手合作&#xff0c;共同发布并开源了 Go 语言的编译时自动插桩技术。该技术以其零侵入的特性&#xff0c;为 Go 应用提供了与 Java 监控能力相媲美的解决方案。开发者只需将 go build 替换为新编译命令 o…...

ScratchLLMStepByStep:训练自己的Tokenizer

1. 引言 分词器是每个大语言模型必不可少的组件&#xff0c;但每个大语言模型的分词器几乎都不相同。如果要训练自己的分词器&#xff0c;可以使用huggingface的tokenizers框架&#xff0c;tokenizers包含以下主要组件&#xff1a; Tokenizer: 分词器的核心组件&#xff0c;定…...

G1原理—10.如何优化G1中的FGC

大纲 1.G1的FGC可以优化的点 2.一个bug导致的FGC(Kafka发送重试 subList导致List越来越大) 3.为什么G1的FGC比ParNew CMS要更严重 4.FGC的一些参数及优化思路 1.G1的FGC可以优化的点 (1)FGC的基本原理 (2)遇到FGC应该怎么处理 (3)应该如何操作来规避FGC (4)应该如何操…...

当多线雷达遇上RTK:一个能跑工业现场的SLAM方案

多传感器融合建图及定位的工程化落地方案&#xff0c;多线雷达rtk&#xff1b;室内室外导航都适用。 包含部署文档和代码注释&#xff1b;包含工程落地角度的优化。 不含运动控制。 室外场景用RTK信号稳如老狗&#xff0c;一进厂房立马抓瞎&#xff1b;多线雷达在室内横扫千军…...

源网荷储全场景适配:新型电力系统时序数据库落地指南

新型电力系统应该用什么数据库&#xff1f;源网荷储四侧的时序数据库选型与落地实战 “双碳”目标的推进正在深刻重构电力系统的运行逻辑。新能源装机占比持续攀升&#xff0c;储能、虚拟电厂、需求响应等新业态快速涌现&#xff0c;源、网、荷、储各侧的角色与互动方式正在被…...

告别SIFT/ORB!用LoFTR+Transformer搞定低纹理场景的图片匹配(附Python实战代码)

低纹理场景图像匹配实战&#xff1a;LoFTR与Transformer的革新应用 在计算机视觉领域&#xff0c;图像特征匹配一直是三维重建、视觉定位等任务的基础环节。传统方法如SIFT、ORB依赖于特征检测器提取关键点&#xff0c;但在低纹理、重复图案或运动模糊场景中表现往往不尽如人意…...

巨有科技:银发文旅风口来了!康养旅游这样做才赚

随着老龄化社会加深与全民健康意识提升&#xff0c;康养旅游成为2026年文旅行业最具潜力的风口赛道&#xff0c;银发旅游群体持续壮大&#xff0c;成为文旅市场核心增量。但当下康养旅游普遍存在产品单一、服务不专业、运营不规范、适配性不足等问题&#xff0c;传统观光式旅游…...

tkinter表格神器tkintertable实战:5分钟搞定可拖拽编辑的数据表格(附完整代码)

tkinter表格神器tkintertable实战&#xff1a;5分钟搞定可拖拽编辑的数据表格&#xff08;附完整代码&#xff09; 在Python GUI开发中&#xff0c;表格控件一直是刚需但实现起来又颇为棘手的组件。传统tkinter自带的Treeview虽然能勉强实现表格功能&#xff0c;但在交互体验上…...

当孩子冲动行为影响学习,如何借助哈洛韦尔医生的情绪管理技巧?

如何有效应对孩子情绪管理困难&#xff0c;促进学习进步 面对孩子的情绪管理困难&#xff0c;家长和教育者可以采用一些实用的策略来帮助他们更好地表达情绪和应对挑战。首先&#xff0c;建立一个安全的环境非常重要&#xff0c;让孩子感到可以自由表达自己的情感而不必担心负面…...

音频标注:从原理到产业,AI听懂世界的“翻译官”

音频标注&#xff1a;从原理到产业&#xff0c;AI听懂世界的“翻译官” 引言 在人工智能的浪潮中&#xff0c;计算机视觉的“看”和自然语言处理的“读”已广为人知&#xff0c;而让机器学会“听”——理解并解析复杂的声音世界&#xff0c;正成为新的前沿。这一切的基石&…...

4 种可靠的 OPPO 手机联系人备份到电脑的方法

OPPO 手机的全球出货量常年位居前五&#xff0c;足以见得它已经获得了越来越多用户的认可。对于年轻群体而言&#xff0c;入手一款高性价比的 OPPO Reno4 SE 这类机型是非常不错的选择。但日常使用中&#xff0c;误操作、进水等意外都可能导致数据丢失&#xff0c;为了避免这类…...

Windows 11优化终极指南:一键清理预装软件与提升系统性能

Windows 11优化终极指南&#xff1a;一键清理预装软件与提升系统性能 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本&#xff0c;用于从Windows中移除预装的无用软件&#xff0c;禁用遥测&#xff0c;从Windows搜索中移除Bing&#xff0c;以及执行各种其他更改以简化…...

告别‘缺少DLL’:用EnigmaVB给Qt5.14程序封包的保姆级避坑指南

告别“缺少DLL”困境&#xff1a;EnigmaVBQt5.14封包全流程实战手册 当你用Qt Creator完成开发&#xff0c;满怀期待地将程序打包发给用户&#xff0c;却收到“缺少xxx.dll”的报错反馈时&#xff0c;这种挫败感开发者都深有体会。本文将以Qt5.14为例&#xff0c;结合EnigmaVB封…...