< 返回新闻公共列表
					
						
						
JVM内存
						发布时间:2023-06-26 14:00:02
						
						
							
JVM学习(️ 深入理解Java虚拟机)
- JVM内存管理脑图

 - JVM是什么?
 
- JVM(Java Virtual Machine 简称JVM),是Java的核心所在。也是Java语言与平台无关性的基础
 - 参考软件架构风格中虚拟机风格中的解释器风格
 
- Sun Classic(始祖)
 - HotSpot(运用最广)
 - 等其他虚拟机
 
第一节:JVM的内存结构
如图:
JDK- 6结构(CV大法)
- 如图:

 
JDK- 8结构(CV大法)
- 如图:

 - 是否由所有线程共有?
 
- 程序计数器(私有):当前线程所执行的字节码的行号指示器,这是唯一一个不会发生OOM的区域
 - 虚拟机栈(私有):保存了方法执行时的栈帧;栈帧描述了方法执行时的局部变量表、操作数栈、动态连接、**方法出口 **等信息
 
- 局部变量表:描述了编译期可知的基本数据类型(如,byte、char......)
 
- 本地方法栈(私有):与虚拟机栈类似,但是本地方法栈为Native(本地)方法服务;而虚拟机栈为Java方法服务
 - 堆(共享):大部分的Java实例对象都在堆里面,也是GC的管理区域
 - 方法区(共享):存放着类型信息、常量、静态变量等数据
 
- JDK- 8放弃永久代,改用元空间
 - 运行时常量池属于方法区,运行时常量池用于存放常量池表(编译时生成的各种字面量、符号引用)
 
第二节:对象
- 自身的运行时数据

 - 类型指针
 
第三节:内存回收
程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭,不需要GC
第四节:如何判断对象已经“死亡”
内存的回收的前提是对象已经死亡,也就是说不存在任何的引用,因此如何判断对象已死,这十分重要
- 原理:存在引用则加一,减少引用则减一,为0时,说明对象不存在引用(已经死亡)
 - 优势:简单易于实现
 - 缺点:无法解决循环引用
 
- 原理:如果任何对象可以找到GCRoots根节点,则认为该对象存活否则死亡
 - 卡表:解决跨代引用,JVM做全堆扫描的性能问题
 - 写屏障:维护卡表的状态,防止出现脏读;即便写屏障存在性能损耗,但是依然优于全堆扫描
 - 如图所示:

 
- 对象至少需要经历两次标记
 - 第一次标记:对象与GcRoots没有关联
 - 第二次标记:经历一次标记的对象是否有必要执行finalize();这是对象"自救"的最后一步 //TODO:2023/3/21日发布前四章
 
第五节:垃圾收集算法
分代收集理论
- 弱分代假说:大部分对象都朝生夕灭
 - 强分代假说:熬过越多次GC的对象,则对象越难以消亡
 - 跨代引用假说:跨代引用相对于同代引用来说,仅占极少数
 
- 新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。
 - 老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。
 - 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。
 
分代收集算法
- 首先标记存活\死亡的对象,然后回收被标记\未标记的对象
 - 缺点:内存碎片化严重、执行效率不稳定
 - 如图:

 
- 为了解决标记-清除算法效率较低
 - 将内存划分为两块,一次只是用其中一块,当一块内存已经使用完时,将存活的对象移动至另一块,在一次性清理使用完成的内存块。
 - 缺点:内存浪费严重
 - 如图:

 
- 为了解决标记-复制算法当存活对象较多时,复制效率较低;且浪费大量空间
 - 与标记-清除算法类似,但是不需要清除对象;而是将存活的对象移动到内存某一侧,然后清除另一侧的对象
 - 缺点:需要暂停用户线程保证一致性,性能与一致性需要综合考虑
 - 如图:

 
- 目的:暂停用户线程;
 - 为何?当GC时,为了保证对象标记、清除的正确性、完整性。需要STW,因为如果不STW,会导致标记错误。
 
- 白色:不可达
 - 灰色:已经被垃圾收集器扫描,但是还存在未扫描引用
 - 黑色:对象及其引用全部被扫描
 - 如何解决对象消失问题:
 - 增量更新:当存在黑色指向白色的引用时,记住当前黑色对象;在并发扫描之后,重新扫描。( 一旦存在黑引用白,则修改黑为灰)
 - 原始快照:当存在灰色删除白色引用时,记录白色对象;在扫描结束后,以灰色为根,重新扫面。( 不在乎是否真的删除,因为永远都会以开始扫描的对象图来进行搜索)
 
第六章 垃圾收集器
- GC线程为单线程
 - 如图:

 
- GC线程多线程
 - 如图:

 
- 基于标记-复制算法
 - 与ParNew相似
 - Parallel Scavenge关注的是吞吐量;区别于其它垃圾收集器,它不关注用户线程暂停时间
 
- CMS(Concurrent Mark Sweep)收集器
 
- 基于标记-清除算法
 - 关注服务的响应时间,希望系统的停顿时间尽量短
 - 采用增量更新解决标记对象消失
 - 包含四步
 
- 初始标记(需要STW);标记GcRoots能直接关联的对象
 - 并发标记(不需要STW);从GcRoots直接关联的对象开始遍历对象图
 - 重新标记(需要STW);修正在并发阶段,线程修改的对象标记
 - 并发清除(不需要STW);并发删除对象
 
- CMS示意图

 
- 局部基于标记-复制算法,整体基于标记-整理算法
 - 采用原始快照解决标记对象消失
 - G1收集器区别于其余的收集器,不在于数据的分代(但是依然遵循分代理论);G1将内存分治为多个Region,优先回收收益最高的Region
 - G1运行过程
 
- 初始标记:仅标记GcRoots能直接关联的对象(需要STW)
 - 并发标记:从GcRoots开始进行全图的可达性分析
 - 最终标记:修正并发标记阶段被修改的标记(需要STW)
 - 筛选回收:对Region的价值进行评估,复制旧的Region中存活的实例到新的Region,清理旧的Region(需要STW)
 
- 如图:
