JVM知识总结
1.概述
JVM指的是Java虚拟机,本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件,作用是为了支持跨平台特性。
功能:
-
装载字节码,解释/编译为机器码
-
管理数据存储和垃圾回收
-
优化热点代码提升效率
2.构成
-
类加载子系统:从硬盘上加载字节码文件到JVM
-
运行时方法区:按照不同的数据分区存储(方法区,栈,堆,本地方法栈,程序计数器)
-
执行引擎:将字节码再次编译/解释为机器码
-
本地库接口:负责调用本地方法

3.类加载子系统

3.1加载
-
通过类的全限类名获得此类的二进制字节流
-
将静态存储转化为运行时存储(方法区)
-
在内存中生成该类的class对象
3.2链接
验证:检验被加载的字节码是否正确
1.文件格式验证,比如文件是否以0xCAFEBABE开头,主次版本号是否满足当前Java虚拟机版本要求。 2.元信息验证,例如类必须有父类(super不能为空)。 3.验证程序执行指令的语义,比如方法内的指令执行到一半强行跳转到其他方法中去。 4.符号引用验证,例如是否访问了其他类中private的方法等。
准备:为该类的静态属性分配内存,并设置默认值(不包括被final修饰,此时会直接赋值,因为在编译时就被加载)


解析:将常量池中二进制的符号引用替换成直接引用,符号引用就是在字节码文件中使用编号来访问常量池中 的内容。直接引用不在使用编号,而是使用内存中地址进行访问具体的数据。

3.3初始化
为类的静态变量赋初值,执行字节码文件中clint部分的字节码指令
3.4类初始化时机
-
使用类中的静态变量,静态方法
-
创建对象
-
运行main方法
-
反射
-
初始化子类
4.运行时数据区
4.1程序计数器
记录程序执行的位置,不会出现内存溢出的情况,内存小,速度快,是线程私有的,不会进行垃圾回收
4.2虚拟机栈
一个方法入栈后,可以看作是一个栈帧
-
局部变量表:存放方法的参数和局部变量
-
操作数栈:在执行指令时用来存放临时数据的一块区域
-
返回地址:当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保 存一个方法返回地址。
4.3本地方法栈
存放本地方法,线程私有,会造成内存溢出,不会进行垃圾回收.
本地方法:被native修饰的方法,没有方法体,例如
native hashCode() 内存地址 native getClass(); native Object clone() native void notify(); native void notifyAll(); native void wait(long timeout) FileInputStream native int read0() Thread native void start0();
4.4堆
存放程序中的对象实例,共享线程,会内存溢出,会进行垃圾回收,是JVM管理最大的一块内存空间
-
分区

为什么分区?
根据存活时间的长短进行划分,生命较长的对象放在老年代减少垃圾回收次数和扫描频率
对象分区流程
-
新创建的对象存放在伊甸园区
-
当垃圾回收时,将伊甸园存活的对象移入到幸存者0区
-
再次创建的新对象还是在伊甸园区
-
下一次垃圾回收到来时会将伊甸园区存货的对象和幸存者0存活的对象转至幸存者1区,始终保持幸存者区有一个是空的
-
当一个对象经过15次垃圾回收后仍然存活,该对象被移入老年区
-
当老年代中空间不足,无法放入新的对象时,先尝试major gc如果还是不足,就会触发Full GC,Full GC会对整个堆进行垃圾回收。
4.5方法区
在不同的hotspot版本中会使用永久代和元空间来实现主要包括:
-
每一个加载的类的基本信息
-
运行时常量池,保存了字节码文件中的常量池信息
大小可调节并且线程是共享的,但会造成内存溢出

5.本地方法接口
底层由非Java代码实现,并不提供方法体,由于高级语言无法直接访问底层的硬件,所以需要调用操作系统提供的接口进行访问。
6.执行引擎
将装载到虚拟机的字节码编译为机器码
-
前端编译:.java---->.class
-
后端编译:.class---->机器码
6.1解释执行
用一个解释器对代码逐行进行解释,一般用于脚本语言(效率低,但省去了编译时间)
6.2编译执行
一次性的对代码进行整体编译(编译费时,但执行效率高)
6.3解释器和JIT编译器
-
解释器:当 Java 虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。
-
JIT(Just In Time Compiler)编译器:就是虚拟机将源代码一次性直接编译成和本地机器平台相关的机器语言,但并不是马上执行。
在Java中采用半解释半编译的方式将字节码转化为机器码,程序刚开始执行时解释器就会立即执行,但在运行过程中,会将热点代码编译并缓存,二者结合达到一个平衡点
7.JDK6-8内存区域的区别
7.1方法区的实现
使用元空间替换永久代的原因: 1、提高内存上限:元空间使用的是操作系统内存,而不是JVM内存。如果不设置上限,只要不超过操作系统内存 上限,就可以持续分配。而永久代在堆中,可使用的内存上限是有限的。所以使用元空间可以有效减少OOM情况 的出现。 2、优化垃圾回收的策略:永久代在堆上,垃圾回收机制一般使用老年代的垃圾回收方式,不够灵活。使用元空间 之后单独设计了一套适合方法区的垃圾回收机制
7.2字符串常量池的位置
字符串常量池从方法区移动到堆的原因: 1、垃圾回收优化:字符串常量池的回收逻辑和对象的回收逻辑类似,内存不足的情况下,如果字符串常量池中的 常量不被使用就可以被回收;方法区中的类的元信息回收逻辑更复杂一些。移动到堆之后,就可以利用对象的垃圾 回收器,对字符串常量池进行回收。 2、让方法区大小更可控:一般在项目中,类的元信息不会占用特别大的空间,所以会给方法区设置一个比较小的 上限。如果字符串常量池在方法区中,会让方法区的空间大小变得不可控。 3、intern方法的优化:JDK6版本中intern () 方法会把第一次遇到的字符串实例复制到永久代的字符串常量 池中。JDK7及之后版本中由于字符串常量池在堆上,就可以进行优化:字符串保存在堆上,把字符串的引用放入 字符串常量池,减少了复制的操作
8.类加载器
类加载器负责在类的加载过程中将字节码信息以流的方式获取并加载到内存中

1.启动类加载器
JDK9之前由C++编写,JDK9之后由Java编写
2.拓展类加载器
JDK提供的,使用Java编写的加载器,派生于 ClassLoader 类.
3.应用类加载器
加载我们自己定义的类,用于加载用户类路径(classpath)上所有的类
4.自定义加载器
我们自己写一个类继承ClassLoder再例如tomcat这种容器,都会有自己加载类的加载器,重写findClass方法。
9.双亲委派机制
双亲委派机制指的是:当一个类加载器接收到加载类的任务时,会向上查找是否加载过,再由顶向下进行加载。如果上级找不到,就逐级向下委托,使用子级类加载器加载的类,如果都找不到,就报异常了。
作用:
-
保证类加载的正确性避免恶意代码来替代系统类库中的类,比如java.lang.String
-
避免同一个类被重复加载
9.1如何打破
实现自定义类加载器重写findClass()方法,将其中双亲委派机制的代码删除
10.垃圾回收
没有任何引用指向的对象,一直占用内存空间知道程序结束,被保留的空间的无法对其他对象使用,严重的会导致内存溢出。早期的垃圾回收:c/c++程序员手动在程序中对不使用的对象进行删除,如果忘记回收会造成内存泄漏
10.1内存溢出和内存泄漏
-
内存溢出:垃圾回收速度跟不上内存占用的速度
-
内存泄漏:对于对象不被使用,但GC无法回收的对象,导致OOM,是内存溢出的原因之一
例如:数据库连接 dataSourse.getConnection(),网络连接 socket 和 io 连接必须手动 close,否则是不能被回收的。
10.2STW
Stop-the-World,简称 STW,指的是 GC 事件发生过程中,会产生应用程序的停顿。当进行垃圾回收时,会导致其他用户线程暂停。可达性分析算法中枚举根节点(GC Roots)会导致所有 Java 执行线程停顿,为什么需要停顿所有 Java 执行线程?
-
分析工作必须在一个能确保一致性的快照中进行
-
一致性指整个分析期间整个执行系统看起来像被冻结在某个时间点上
-
如果出现分析过程中对象引用关系还在不断变化,则分析结果的准确性无法保 证,会出现漏标,错标问题
10.3标记阶段
主要是为了判断对象是否为垃圾对象
算法:
-
引用计数算法:被引用时+1。缺点:单独维护一个计数器,增加了内存空间占用,会造成循环引用
-
可达性分析算法:以根(GCRoots)为起点搜索被跟所连接的对象是否可达
10.3.1哪些对象被称之为GC Root对象
-
线程Thread对象,引用线程栈帧中的方法参数、局部变量等。
-
系统类加载器加载的java.lang.Class对象,引用类中的静态变量。
-
监视器对象,用来保存同步锁synchronized关键字持有的对象。
-
本地方法调用时使用的全局对象
10.3.2finalize方法
回收前调用,且只会调用一次,在被回收前此方法会执行一些需要的逻辑。由于 finalize()方法的存在,虚拟机中的对象一般处于三种可能的状态.
可触及的:从根节点开始,可以到达这个对象。 可复活的:对象的所有引用都被释放,但是对象有可能在 finalize()中复活。 不可触及的:对象的 finalize()被调用,并且没有复活,那么就会进入不可触及 状态。
以上 3 种状态中,是由于 finalize()方法的存在,进行的区分。只有在对象不可触及时才可以被回收
10.4回收阶段

标记-清除算法
概述:1.标记阶段:将存活对象进行标记,使用可达性分析算法寻找所有的存活对象
2.清除:删除没有别标记的对象
优点:操作简单,只需要维护标志位即可,无需进行对象的移动
缺点:会造成内存碎片化,很有可能这些内存单元的大小过小无法进行分配。由于内存碎片的存在,需要维护一个空闲链表,极有可能发生每次需要遍历到链表的最后才能获得合适的内存空间。
标记-复制算法
概述:准备两块空间,From和To,在对象分配期间只使用其中一块空间,GC阶段将From存活的对象复制到To中,再将两块空间名字互换
优点:不会造成内碎片,只需遍历一次,性能较好
缺点:会进行对象的移动,只有一半的空间来创建对象使用
标记-压缩算法
概述:1.标记阶段:将所有的存活对象的进行标记,使用可达性分析算法寻找所有的存活对象
2.整理阶段:将存活的对象移动到堆的一端
优点:内存利用率高,不会出现碎片化
缺点:造成对象移动,要选择合适的压缩算法
分区收集
-
分代回收时,创建出来的对象,首先会被放入Eden伊甸园区。
-
随着对象在Eden区越来越多,如果Eden区满,新创建的对象已经无法放入,就会触发年轻代的GC,称为Minor GC或者Young GC。Minor GC会把需要eden中和From需要回收的对象回收,把没有回收的对象放入To区
-
如果Minor GC后对象的年龄达到阈值(最大15,默认值和垃圾回收器有关),对象就会被晋升至老年代。当老年代中空间不足,无法放入新的对象时,先尝试minor gc如果还是不足,就会触发Full GC,Full GC会对整个堆进行垃圾回收。
-
如果Full GC依然无法回收掉老年代的对象,那么当对象继续放入老年代时,就会抛出Out Of Memory异常。
11.垃圾回收器

11.1Serial+SerialOld
Serial是是一种单线程串行回收年轻代的垃圾回收器。
11.2Parallel Scavenge+Parallel Old
PS+PO是JDK8默认的垃圾回收器,多线程并行回收,关注的是系统的吞吐量。具备自动调整堆内存大小的特点。
11.3ParNew
ParNew垃圾回收器本质上是对Serial在多CPU下的优化,使用多线程进行垃圾回收
11.4CMS(老年代)
CMS垃圾回收器关注的是系统的暂停时间,允许用户线程和垃圾回收线程在某些步骤中同时执行,减少了用户线程的等待时间。

优点:停顿时间少
缺点:使用标记-清除算法造成内存碎片较多
11.5G1
将每个区域(伊甸园,幸存者,老年代)又划分成若干个小的区域,哪个区域垃圾数量多,优先回收哪个区域,可以做到整堆管理收集也可以做到并发执行
未完待续......
相关文章:
JVM知识总结
1.概述 JVM指的是Java虚拟机,本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件,作用是为了支持跨平台特性。 功能: 装载字节码,解释/编译为机器码 管理数据存储和垃圾回收 优化热点代码提升效率 …...
读书笔记-《数据结构与算法》-摘要8[桶排序]
桶排序和归并排序有那么点点类似,也使用了归并的思想。大致步骤如下: 设置一个定量的数组当作空桶。Divide - 从待排序数组中取出元素,将元素按照一定的规则塞进对应的桶子去。对每个非空桶进行排序,通常可在塞元素入桶时进行插入…...
【STM32调试】寄存器调试不良问题记录持续版
STM32寄存器调试不良问题记录 NVIC(内嵌的中断向量控制器)EXTI(外部中断/事件) 记录一些stm32调试过程中:不易被理解、存在使用误区、不清不楚、是坑、使用常识等方面的一些记录。本记录只包含stm32的内核以及外设等寄…...
centos7 arm服务器编译升级安装动态库libstdc++.so.6,解决GLIBC和CXXABI版本低的问题
前言 由于centos7内置的libstdc.so.6版本太低,导致安装第三方包的时候,会报“CXXABI_1.3.8”不存在等问题。 自带的打印如下: strings /usr/lib64/libstdc.so.6 | grep GLIBC strings /usr/lib64/libstdc.so.6 | grep CXXABI 如图 升级 注…...
自动驾驶轨迹规划之碰撞检测(三)
欢迎大家关注我的B站: 偷吃薯片的Zheng同学的个人空间-偷吃薯片的Zheng同学个人主页-哔哩哔哩视频 (bilibili.com) 目录 1.基于圆覆盖 2.BVH 3.MATLAB自动驾驶工具箱 4 ROS内置的模型 自动驾驶轨迹规划之碰撞检测(一)-CSDN博客 自动驾…...
如何用pandas处理财报数据删除金融行业数据
要删除财报数据中的金融行业数据,您可以按照以下步骤使用pandas进行处理: 导入pandas库: import pandas as pd读取财报数据文件: df pd.read_csv(财报数据.csv)查看数据中的行业分类列: print(df[行业分类])确定金…...
oracle 19c容器数据库data dump数据泵传输数据(4)---网络传输
Transporting a Database Over the Network: Example 这个的方式导入可以不需要传输dmp文件,我原本是想从11g导入到pdb2的,但是因为版本的原因,就直接实验从pdb1导入到pdb2吧。 这种方式和前面完全传输的方式类似,不需要事先在目…...
IP 网络分为接入网、城域网和骨干网
根据前述的IP 网络设计思想,结合算力网络对 正网络的需求分析,卫网络的具体实现可以从架构设计利网络技术两个方面进行总体设计。 首先从架构设计上考虑,架构应尽量简化,做到“以简应繁”。因此,整体网络架构不宜设计…...
web3.0基本概念简析
web3.0概念简析 web3.0的发展史 web1.0 仅用于展示,无法进行点赞评论等交互 web2.0 不仅可以展示,还可以上传视频、图片等,用户可以参与创作内容并获取收益。但还是中心化的模型 缺点 1 机械化的人机验证 2 账户安全无法保证 多年未登陆…...
Linux/Traceback
Enumeration nmap 使用nmap初步扫描发现只开放了22和80端口,端口详细扫描情况如下 先看看web是什么样子的,打开网站发现有一条留言,显示该站点已经被黑了, 并且留下了后门 查看源代码,可以看到下面的注释 <!--So…...
陶瓷碗口缺口检测-图像分割
图像分割 由于对碗口进行缺口检测,因此只需要碗口的边界信息。得到陶瓷碗区域填充后的图像,对图像进行边缘检测。这是属于图像分割中的内容,在图像的边缘中,可以利用导数算子对数字图像求差分,将边缘提取出来。 本案…...
2023年第十四届蓝桥杯软件赛省赛总评
报名明年4月蓝桥杯软件赛的同学们,如果你是大一零基础,目前懵懂中,不知该怎么办,可以看看本博客系列:备赛20周合集 20周的完整安排请点击:20周计划 每周发1个博客,共20周。 在QQ群上交流答疑&am…...
Redis面试大全
1、什么是Redis? Redis是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。 Redis与其他key-value缓存产品有以下三个特点: Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次…...
MFC为资源对话框添加消息处理函数和初始化控件
现在我VC6新建了一个对话框工程;又在资源添加了一个新的对话框,并为新的对话框添加了名为CTestDlg的类; 在主对话框的cpp文件包含#include "TestDlg.h"; 在主对话框的cpp文件的OnInitDialog()成员函数中,添…...
7.6 MySQL基本函数的使用(❤❤❤)
7.6 MySQL基本函数的使用 1. 提要2. 数字函数3. 字符函数3.1 替换字符3.2 左填充字符及截取字符串 4. 日期函数4.1 日期函数4.2 表达式占位符4.3 日期偏移计算4.4 日期间隔 5. 条件函数5.1 IF语句5.2 case...when语句 1. 提要 2. 数字函数 3. 字符函数 3.1 替换字符 -- INSERT…...
《Redis:NoSQL演进之路与Redis深度实践解析》
文章目录 关于NoSQL为什么引入NoSQL1、单机MySQL单机年代的数据库瓶颈 2、Memcached(缓存) MySQL 垂直拆分 (读写分离)3、分库分表水平拆分MySQL集群4、如今的网络架构5、总结 NoSQL的定义NoSQL的分类 Redis入门Redis能干嘛&…...
npm依赖库备份
常用命令 设置默认使用本地缓存安装Nodejs时会自动安装npm,但是局路径是C:\Users\Caffrey\AppData\Roaming\npm默认的缓存路径是C:\Users\Caffrey\AppData\Roaming\npm-cache;查看npm的prefix和cache路径配置信息设置路径 设置默认使用本地缓存 npm con…...
Python进程池multiprocessing.Pool
环境: 鲲鹏920:192核心 内存:756G python:3.9 python单进程的耗时 在做单纯的cpu计算的场景,使用单进程核多进程的耗时做如下测试: 单进程情况下cpu的占用了如下,占用一半的核心数: 每一步…...
[leetcode~数位动态规划] 2719. 统计整数数目 hard
给你两个数字字符串 num1 和 num2 ,以及两个整数 max_sum 和 min_sum 。如果一个整数 x 满足以下条件,我们称它是一个好整数: num1 < x < num2 min_sum < digit_sum(x) < max_sum. 请你返回好整数的数目。答案可能很大ÿ…...
【Vue3】2-13 : 章节总结
本书目录:点击进入 一、总结内容 二、习题 2.1 【选择题】以下Vue指令中,哪些指令具备简写方式? 2.2 【编程题】以下Vue指令中,哪些指令具备简写方式? > 效果 > 代码 一、总结内容 了解核…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
