JVM(Java Virtual Machine)
目录JVM-Java虚拟机/解释器一次编写到处编译一次编写到处执行JVM三个核心内容面试常考1.JVM内存区域划分1.程序计数器2.栈虚拟机栈栈帧本地方法栈3.堆4.元数据区类的元信息类对象反射5.补充内存溢出线程、进程内存的不同2.JVM类加载机制1.类加载流程加载验证ClassFile准备针对字符串常量进行初始化初始化2.类加载的时机3.双亲委派模型3.JVM的垃圾回收1.找出垃圾1.引入2.可达性分析GCRoots2.识别出是垃圾之后如何释放内存1.标记清除2.复制算法标记整理分代回收·结语·JVM-Java虚拟机/解释器JVM可以实现“一次编写到处运行”。创建一个进程就会自动创建一个JVM。开发Java代码需要下载JDK只是运行只需下载JRE即可。一次编写到处编译像C/C这些语言都没有“虚拟机”这个机制所以写一个代码使用A平台编译生成一个A的可执行程序使用B平台编译生成一个B的可执行程序在切换平台的时候就可能要调整代码且不同的CPU有不同的指令集和不同的操作系统有不同的API。一次编写到处执行而像Java/python/JavaScript等都引入了“虚拟机”实现“一次编写到处运行”。.java文件编译成.class字节码文件把字节码文件打包成一个.jar包不同版本的Java虚拟机都可以解释执行相同的字节码。JVM三个核心内容面试常考1.JVM内存区域划分内存区域分为4部分注以下的堆、栈都是JVM上的不要和数据结构、操作系统搞混1.程序计数器程序计数器只存一个数字这个值是下一条要执行的Java字节码指令的地址。2.栈虚拟机栈给Java程序使用的栈用来维护方法的调用信息。调用方法时按照调用顺序压入虚拟机栈先进后出。栈帧栈帧存的是1.调用方法的参数信息2.方法内部的局部变量3.方法结束后要返回的上一层方法的位置4.返回值本地方法栈当Java代码调用到native方法时就把栈帧压入本地方法栈栈帧记录着C/C方法的信息。注本地方法栈与虚拟机栈的栈帧记录的内容不同。native方法源码不在JVM中在JDK的源码包中运行时源码被编译为动态库文件xxx.dllJVM启动时会加载这个动态库里面是机器码。3.堆最大的内存空间new的对象都在堆上。4.元数据区元数据区存的是 类的元信息。类对象class实例存放在 堆内存该对象引用指向 元数据区的 类的元信息。类的元信息类元信息指的是JVM运行时把.class文件读取到内存中解析出来通过一些特定的结构表示的原始模板数据存在元空间。类元信息包括类名、父类、接口、方法、成员变量的定义、static属性、常量池等这个类的所有信息。类对象类对象指的是JVM为这个类创建的普通对象的实例类对象包括持有引用指向元空间的类元信息提供一堆方法反射API用来读取元空间的元信息反射程序运行期间拿到一个类的全部信息运行时才知道类是谁。//拿到Class类对象 Class clazz Demo.class; //拿到test方法 Method method clazz.getMethod(test); //调用方法 method.invoke( new Demo() );5.补充局部变量存储在栈上成员变量存储在堆上类对象/static修饰的属性 存储在 元数据区上内存溢出栈溢出调用方法信息过多栈帧过多导致栈溢出。堆溢出new的对象太多导致堆溢出。注Java可以手动设置栈空间和堆空间大小。线程、进程内存的不同程序计数器、栈每个线程各有一份堆、元数据区一个进程只有一份。2.JVM类加载机制类加载JVM把.class文件读取放到 内存中构建出类对象 和 生成元信息的过程1.类加载流程分为5步加载找到.class文件打开文件把文件读取到内存中根据“全限定类名”找到对应的.class文件全限定类名例如“java.util.Scanner”.根据“双亲委派模型”来找全限定类名。验证根据读到的二进制内容验证是否是合法的格式。验证依据ClassFile-JVM官方规定的.class文件的二进制结构模板。ClassFile注二进制内容不包含注释u4-》unsigned intu2-》unsigned short1.magic二进制文件通常把开头的四个字节设定成特殊值。设magic的原因是文件的后缀名可以随便改所以不靠谱要设置特殊标记。JVM读到文件的前4个字节如果读到CAFEBABE-》是class文件继续不是CAFEBABE-》不是合法class文件抛出异常加载失败。2.minor_version次要版本,major_version主要版本描述了这个.class文件是通过哪个java版本的编译器生成的。如果是Java17编译出来的.class不能放到Java8的JVM上执行如果是Java8编译出来的.class能放到Java17的JVM上执行“向前兼容”准备准备元数据区。例如:给类对象分配内存所有静态变量同一赋默认值。static int count内存分配count0static int sign,内存分配sign0实例变量s,s2,a,,b不处理.针对字符串常量进行初始化JVM解析Test.class发现字面量“hello”把“hello”放到字符串常量池字符串拿到地址但是实例变量s此时还没有拿到这个地址等到实例初始化初始化执行静态变量显示赋值count100sign没有赋值默认0.执行static静态代码块控制台打印“静态代码块执行”。到这里Test类加载全部结束。静态变量count100sign0保存在元空间的类对象中。2.类加载的时机一个类的类加载只有一次。1.第一次new这个类的实例时2.调用这个类的静态成员变量/静态成员方法时3.子类的加载也会触发父类的类加载。3.双亲委派模型出现在类加载第一步加载找.class文件的全限定类名涉及到类加载器JVM中默认包含3个类加载器BootstrapClassLoader引导类加载器-负责加载Java标准库中的类ExtensionClassLoader扩展类加载器-负责加载Java扩展库中的类ApplicationClassLoader应用类加载器-负责加载第三方库以及当前项目中的类如果在3个类加载器中都找不到全限定类名就会抛出ClassNotFound异常。实际上双亲委派模型是约定了“类加载的优先级”标准库最先加载其次是拓展库最后是第三方库/当前项目类3.JVM的垃圾回收C智能指针应对内存泄露Java垃圾回收GC应对内存泄露JVM引入垃圾回收机制更好地应对内存泄漏不是100%避免。GC回收的是堆上的内容回收时以 对象 为一个单位回收不能以字节为单位!怎么确定一个对象是垃圾呢——》一个对象没有引用指向就是垃圾Java使用对象只能通过引用使用。如果判断不准就不回收JVM有四种引用强引用、弱引用、虚引用、软引用。1.找出垃圾1.引入引用计数Java未采用就是在每个对象的内存上安排一块空间存储一个整数整数的值就是对象引用的个数。如果值为0就释放空间。缺点1.消耗更多的内存空间2.循环引用问题对象无法被释放也无法被使用2.可达性分析JVM专门指派一些线程这些线程周期性的扫描代码中申请的内存自动判定当前这个内存是否已经不再使用了。一个Java代码中对象之间有关联关系这些关系组成很多树/图可达性分析从一个树的根节点开始经过的节点都标记为“可达”JVM知道当前进程中有多少个对象除去标记的为“可达”的剩下的都是“不可达的”不可达的即为垃圾随着代码的执行对象之间的关系也在不停变化因此可达性分析周期性进行。GCRootsGCRootsGC遍历的起点。GCRoots来源于1.栈上局部变量2.常量池引用指向的对象3.所有引用类型的静态成员。一轮GC尽可能地遍历所有GCRoots尽可能标记可达。缺点消耗更多的CPU资源消耗更多的时间。2.识别出是垃圾之后如何释放内存1.标记清除清除垃圾后内存不连续。内存碎片会造成无法申请连续大内存问题2.复制算法把内存分为两步分要删除13把24复制一份到右边然后删除左边部分全部的优避免了内存碎片问题。缺空间利用率小复制开销大标记整理标记后类似于顺序表删除删除优避免空间浪费缺复制开销大分代回收Java实际上综合了上述策略构成了一个复杂的方案分代回收根据不同对象的情况/特点采取不同的方案.年龄指标如果某个对象年龄比较大有很大概率存活下去。对象的年龄与GC的扫描轮次、GC的周期有关不是轮次1年龄就1针对老年代的扫描称为Major GC开销较大频率较低针对新生代的扫描称为Minor GC开销较小频率较高1.新new的对象放入伊甸园中2.伊甸园中的对象经过第一轮GC淘汰掉绝大部分。没有淘汰掉的经过复制算法进入幸存区3.下一轮GC会对幸存区的对象扫描再淘汰掉一大批对象。没有淘汰掉的经过复制算法进入另一个幸存区由经验规律发现每轮GC淘汰掉大部分新对象因此触发复制的对象就很少避免了复制算法拷贝开销大的问题幸存区只占10%浪费的内存空间小了。4.随着每轮GC的进行对象就会再新生代的幸存区来回拷贝拷贝一次年龄15.经过一定时间对象的年龄达到一定阈值。把这个对象拷贝到老年代。6.进入老年代之后GC的频率就低了。针对老年代的对象的回收时曹勇 标记整理 的方式处理。7.占据内存很大的对象直接进入老年代上述分代回收过程是简化版真实情况复杂很多·结语山高万仞只登一步

相关新闻

【n8n】ASMR视频创意与多平台分发应用

【n8n】ASMR视频创意与多平台分发应用

短视频创作领域正在经历自动化与智能化的深度融合。通过结合大语言模型与视频生成技术,内容从构思到发布的流程正变得更高效与可控。 该工作流集成了创意生成、脚本编写、视频制作与多平台分发等环节,基于 Google 表格、FalAI 视频生成能力及 Blotato 接口,实现玻璃质感 AS…

2026/9/24 17:51:45 阅读更多 →
记录一次开源物联网平台thinglinks的docker部署步骤

记录一次开源物联网平台thinglinks的docker部署步骤

物联网平台thinglinks部署说明(docker) 由于官网的部署文档找不到内容,自己凭借经验部署并记录了一遍。 安装docker和docker-compose 1.1上传docker-20.10.9.tgz安装包并解压 # tar -zxvf docker-20.10.9.tgz # cp docker/* /usr/bin/…

2026/9/24 17:51:45 阅读更多 →
零基础学SQL 19:报表累计求和总对不上?窗口函数 4 行搞定(附 3 个模板)

零基础学SQL 19:报表累计求和总对不上?窗口函数 4 行搞定(附 3 个模板)

做月度报表,绕不开这三个问题: 截至这个月,累计是多少?跟上个月比,涨了还是跌了?这个月占了整体的百分之多少? 不会窗口函数的人,一般有三条出路:导到 Excel 手动拉一列、…

2026/9/24 17:51:45 阅读更多 →

最新新闻

Linux与Windows系统运维:参数查询与配置命令对照实战

Linux与Windows系统运维:参数查询与配置命令对照实战

很多时候,我们干的活儿并不是什么高深莫测的架构设计,反而是那些每天都在重复的“查一下参数、改一个配置”。尤其是当你的手头同时管着 Windows 服务器和 Linux 服务器时,这种“精神分裂”的感觉会特别明显:明明在 Windows 上用图…

2026/9/24 18:28:13 阅读更多 →
RabbitMQ安装详解:Windows与Docker高频坑与权限排查

RabbitMQ安装详解:Windows与Docker高频坑与权限排查

先聊点实际的。你点进这篇文章,多半是因为项目里突然要用消息队列,或者面试题刷到“RabbitMQ和Kafka怎么选”,又或者已经在Windows上装了RabbitMQ,结果服务死活起不来,管理界面也打不开。不管你是哪种情况,…

2026/9/24 18:28:13 阅读更多 →
Linux与Windows参数查询与配置:双系统实战速查手册

Linux与Windows参数查询与配置:双系统实战速查手册

1. 项目背景:为什么我要维护一份“Linux与Windows参数查询与配置”手册自从开始同时接触Linux服务器和Windows桌面环境,我就一直被同一个问题反复折磨:某个参数上次明明调通了,下次换台机器又得从头翻文档。更让人崩溃的是&#x…

2026/9/24 18:28:13 阅读更多 →
Flutter状态边界:UI树才是决定setState刷新范围的关键

Flutter状态边界:UI树才是决定setState刷新范围的关键

有人问我一个很经典的问题:setState明明调了,数据也变了,界面就是不动,到底哪里出了问题?我听完他的代码描述,第一反应不是去看状态管理库配没配好,而是反问他一句:你这段状态&#…

2026/9/24 18:28:13 阅读更多 →
基于OpenCV模板匹配的车牌识别毕业设计实战指南

基于OpenCV模板匹配的车牌识别毕业设计实战指南

简介:这是一套基于OpenCV模板匹配的车牌识别毕业设计源码,使用Python 3.8与OpenCV 4.2开发,并配有简单的GUI界面。项目面向计算机相关专业的学生或课程设计用户,主要解决从车辆图像中定位车牌、校正倾斜、判别牌照颜色、分割字符并…

2026/9/24 18:28:13 阅读更多 →
【Coze】【视频】治愈系老爷爷工作流

【Coze】【视频】治愈系老爷爷工作流

今天给大家演示一个 老爷爷语录视频自动生成工作流。该工作流通过大语言模型和图像生成模型的协作,自动完成从文本语录生成、格式化处理、配图生成,再到视频合成和音频配乐的完整流程。结合效果展示,用户只需提供简单的输入,就能得到带有温馨画面和背景音乐的成品视频,大幅…

2026/9/24 18:27:12 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →