03-JVM虚拟机
2025-01-15 19:44:54 3 举报
AI智能生成
03-JVM虚拟机的核心内容包括对Java程序执行的抽象描述。JVM即Java虚拟机,是一种抽象的计算机,可以在任何设备或操作系统上提供执行Java字节码的能力。这一过程涉及类加载器、内存区域划分、执行引擎等重要组成部分。 在文件类型方面,JVM虚拟机通常不直接关联特定文件类型,因为它关注的是字节码的运行,字节码通常编译自Java源代码文件(.java文件),之后编译为.class文件包含字节码。 修饰语方面,JVM虚拟机是可移植的,即同一份字节码可以在任何实现了相应JVM的平台上运行,不受物理硬件或操作系统影响。此外,JVM还提供自动内存管理机制,如垃圾回收,提高了开发者的生产力,也使得Java应用可以相对容易地管理内存。 总结而言,JVM虚拟机作为Java语言的核心技术之一,实现了Java的跨平台运行以及内存管理自动化,对后端开发有着深远的影响。
作者其他创作
大纲/内容
3.2 垃圾回收
常用算法
垃圾回收器
三色标记算法
一种增量标记算法
基本概念
白色对象:还没被垃圾回收器访问的对象,可能是垃圾
灰色对象:已经访问到了,但其引用的对象还没处理完
黑色对象:访问到并且其引用对象处理完毕,这些对象不会被回收
标记过程
初始状态:所有对象都是白色的
标记对象:从根对象(GC Root)开始,把根标记成灰色,然后递归扫描所有灰色对象,当灰色对象所有引用都处理完毕,灰色对象变黑
最终:所有存活对象都会变黑,未访问的白色对象即为垃圾,会被清除
常见类型
为何分成新生代和老年代?根据对象生命周期特点来优化
新生代:多采用复制算法
Serial 收集器(单线程、单核、单处理器)
ParNew收集器(Serial多线程版)
Parallel Scavenge 收集器(标记-复制,JDK8 默认)
追求最大化CPU时间的利用率
并行处理新生代垃圾回收,适合大规模后台任务处理,注重吞吐量而非延迟
适用场景:吞吐量高的场景或任务
吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 运行垃圾收集时间)
老年代:多使用标记整理或标记清除
Serial Old 收集器(Serial 老年代版本)
Parallel Old 收集器(标记-整理算法,Parallel Scavenge 老年代版本,JDK8 默认)
适用场景:吞吐量高的场景或任务
CMS
并发标记清除收集器
优缺点
优点:追求低延迟,减少GC停顿时间
缺点:可能会产生碎片,并发阶段可能会发生Concurrent Mode Failure,导致Full GC
分支主题
适用平台:适用于响应时间要求高的应用,如Web服务和电商平台
回收流程如下
初始标记:标记所有根对象直接可达的对象(职责归STW,Stop-The-World,下同)
并发标记:垃圾收集器与应用线程并发运行,从上一步标记的对象开始tracing,递归扫描所有可达对象,持续时间较长
并发预清理:分担STW的重新标记的部分工作,标记预清理卡表等
可中断的预清理阶段:和并发预清理一样,但它可以被中断
重新标记:STW,重新遍历一遍新生代GC Roots、卡表等
并发清理:标记为不可达的对象会被清除(与应用线程并发运行)
并发重置:重置cms内部状态
G1
回收流程
并发标记
初始标记,STW
并发阶段:上一步标记的对象开始tracing,递归扫描所有可用对象,SATB也会在这个阶段记录着变更的引用
最终标记,STW,处理SATB中的引用
清理阶段,STW
对象拷贝,STW
G1调优: 看扩展部分
ZGC
Java 11 引入,主要支持大内存
特点:
并发收集
指针压缩
无停顿/极小停顿
为什么要调优(调优目标)
减少应用程序的停顿时间
提高应用的吞吐量
两者只能选其一,较难平衡,故需要明确应用目标
核心知识点脑图(感谢图灵教育赞助)
分支主题
3.1 虚拟机
组成
类加载器子系统(ClassLoader)
把.class文件加载到JVM中
加载过程参看:
作用
动态加载类
隔离不同的类命名空间
运行时数据区(Runtime Data Area)
方法区:
存储类信息、常量、静态变量和即时编译器(JIT)编译后的代码
属于线程共享区域,所有线程均可访问
JDK 8 前使用永久代实现,现在使用元空间(本地内存)取代
堆:
存放所有线程共享的对象和数组,是垃圾回收的主要区域
虚拟机栈
每个线程创建一个:存局部变量、操作数栈、动态链接、方法出口信息
局部变量存的是基本数据类型和对象引用
栈线程是私有的,生命周期与线程相同
本地方法栈
为本地方法服务,借助JNI调用本地代码在此区域分配的内存
和虚拟机栈类似,线程私有
程序计数器
是个小内存区域,保存当前线程执行的字节码指令的地址或行号
每个线程都有一个,线程私有
执行引擎(Execution Engine)
解释器:逐行解释字节码并执行,适用于首次运行程序时
即时编译器:将频繁执行的代码编译成机器码,提升执行效率
本地方法接口(Native Interface,JNI)
允许Java程序调用非Java代码
编译执行与解释执行的区别,JVM怎么用的?
区别| 执行方法 | 优点 | 缺点 |
| ---- | --------------- | ---------------------- |
| 编译执行 | 编译后运行速度快,无需二次翻译 | 针对平台编译,跨平台性能差,难以反编译和调试 |
| 解释执行 | 本身就具有跨平台性。开发周期短 | 运行速度慢,每次都需要翻译成机器码 |
JVM实行二者结合的方式编译,详情看组成部分的执行引擎
跨平台的实现
编译后生成.class文件,不直接生成针对某一操作系统的机器代码
不同的操作系统,有不同的JVM环境,负责把字节码翻译成特定平台的机器代码并执行
综上,跨平台成功实现
常用参数
分支主题
**重点背它**
堆和栈的区别
栈:存储局部变量方法和方法调用信息(如返回地址、参数)。在方法执行期间局部变量(包括引用变量,不包括引用对象)创建在栈上,并在方法结束时销毁
堆:用于存储实例对象或数组。使用new关键字创建时,JVM都会在堆上为该对象分配空间
直接内存
由操作系统直接分配,不受JVM堆内存管理限制
通过java.nio中的ByteBuffer.allocateDirect()方法配置
用于绕过JVM垃圾回收机制,直接与本地系统内存交互
常量池
运行时常量池:每个类或接口的Class文件中存储编译时生成的常量信息,并在类加载时进入JVM方法区
字符串常量池:用于存储字符串常量,位于堆内存中的一个特殊区域,通过String的intern() 方法可实现把字符串放入字符串常量池
作用:减少重复对象的创建,节省内存并提高效率
JVM 内存/栈溢出| 错误类型 | 原因 | 解决方法 |
| ---------------------------------- | --------------- | ------------------------------------------ |
| Java Heap Space | 大量对象创建 | 增大堆内存,优化对象使用,-Xmx |
| StackOverflowError | 递归调用、深层嵌套调用 | 增大栈空间,优化递归逻辑,-Xss |
| Metaspace | 频繁生成动态类 | 增大方法区或空间类,减少加载频率 -XX:MaxMetaspaceSize |
| Direct Buffer Memory | 直接内存不足,常见于NIO操作 | 增大直接内存限制或者减少直接内存使用 -XX:MaxDirectMemorySize |
| Unable to Create New Native Thread | 线程数过多 | 控制线程数,检查线程池相关代码 |
| GC Overhead Limit Excceed | GC事件过长且回收内存不足 | 增大堆内存、优化内存使用、调整策略 -Xmx |
NIO
定义:非阻塞I/O模式,只要调用方发起I/O操作就可以立即返回,无论当前操作完成与否
Java中常见的nio操作
多路复用:java.nio.channels.Selector 可以同时管理多个 SocketChannel
直接内存分配
优缺点
优点:
减少线程数量
大幅降低切换开销
提升系统资源利用率
适合处理大量并发连接
缺点:
实现复杂度高
编译
JIT(即时编译)
一种在运行程序时将字节码转换成机器码的技术
对频繁执行的代码(段)编译成机器码,以减少解释开销
存在代码缓存区中(不在堆内)
相关参数
-XX:InitialCodeCacheSize:初始大小
-XX:ReservedCodeCacheSize:最大大小
-XX:+PrintCodeCache:打印Code Cache信息
编译类型:
C1:快速启动的轻量级优化,客户端编译优选
C2:长时间运行的重度优化,服务端编译优选
AOT(预编译)
在程序运行前,把Java字节码直接编译成本地机器码的技术
先对Java字节码进行静态分析,然后编译成目标平台的机器码
优缺点可以参考编译执行的优缺点来背诵
区别:就是时机
逃逸
两种类型:方法逃逸、线程逃逸
方法逃逸:对象在方法内部创建,并作为返回值或通过参数传递给其他方法,会导致该对象逃逸到方法之外
线程逃逸:对象被另一个线程访问,或者被保存为静态变量或共享变量,会导致该对象逃逸到全局
三种优化:栈上分析、标量替换、同步消除
栈上分析:对象没有逃逸出当前方法,JVM可把对象分配到栈上,减少分配内存和垃圾回收的开销
标量替换:如果对象没逃逸且可拆解,JVM可把对象的字段替换成标量,避免对象的内存分配
同步消除:如果对象没有逃逸出当前线程(就在线程内部用),JVM会移除不必要的同步锁,提升性能
如何开启分析
-XX:+DoEscapeAnalysis:默认已开启,启用逃逸分析
-XX:+EliminateLocks:启用同步消除(基于逃逸分析)
-XX+EliminateAllocations:启用标量替换(基于逃逸分析)
性能分析
分支主题
场景题:
0 条评论
下一页
为你推荐
查看更多