JVM(对象生命周期和对象引用以及垃圾收集算法)

第二部分——JVM(对象生命周期和对象引用以及垃圾收集算法)

第一部分:JVM(总结一概念以及内存分类)

三.对象生命周期
四.对象引用
五.垃圾收集算法
六.垃圾收集器

垃圾收集需要完成的三件事情:

  • 什么内存需要收集(判定无用的对象)
  • 什么时候回收(何时启动,不影响程序正常运行)
  • 如何回收(回收过程,要求速度快/时间短/影响小)

三.对象生命周期

  • 对象通过构造函数创建, 但是没有析构函数回收内存‘
  • 对象存活在离它 最近的一对大括号中
  • 垃圾收集

Java程序语言关于内存回收的API

  • Object的finalize方法,垃圾收集器在回收对象时调用,有且仅被调用一次

  • System的gc方法,运行垃圾收集器

简述Java垃圾回收机制
在java中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

GC是什么?为什么要GC
GC 是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。

四.对象引用

基于对象引用判定无用对象

  • 零引用,互引用等

1.引用计数法

  • 一种古老的算法,每当有一个地方引用时,计数器加一,当引用失效,计数器减一;计数器为0的对象,将被回收。
  • 优点: 简单,效率高
  • 缺点: 无法识别对象之间相互循环引用

在这里插入图片描述

2.可达性分析

  • 对象引用链:通过一系列的称为"GCRoots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain) ,如果一个对象到GCRoots没有任何引用链相连,或者用图论的话来说,就是,从GCRoots到这个对象不可达时,则证明此对象是不可用的。

在这里插入图片描述
可固定作为GC Roots的对象包括以下几种:

  • 在虚拟机(栈帧中的本地变量表)中引用的对象,比如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。
  • 在方法区中类静态引用的对象,比如Java类的引用类型静态变量。
  • 在方法区中常量引用的对象,比如字符串常量池里的引用。
  • 在本地方法栈中JNI(即Native方法)引用的对象。
  • Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(比如NullPointExcepiton、OutOfmemoryError)等,还有系统类加载器。
  • 所有被同步锁(synchroniezd关键字)持有的对象。
  • 反应Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

四种强度的对象引用:

  • 强引用:是最传统的“引用”的定义,是指在程序代码之中普遍存在的引用赋值,既类似“Object obj=new Object()”这种引用关系。任何情况下,只要强引用关系还存在,垃圾回收器就永远不会回收掉被引用的对象。
  • 软引用: 用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收。JDK提供了SortReference类来实现软引用。
  • 弱引用: 也是用来描述那些非必须对象,强度比软引用更弱一些。被弱引用关联的对象只能生存到下一次垃圾收集发生为止。JDK提供了WeakReference类来实现软引用。
  • 虚引用: 也被称为“幽灵引用”或者“幻影引用”,它是最弱的一种引用关系。一个对象是否存在虚引用,完全不会对其生存时间造成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被垃圾回收时收到一个系统通知。JDK提供了PhantomReference类来实现软引用。
  • 软引用和弱引用适合用来保存可有可无的缓存数据。
对象引用类型强引用软引用弱引用虚引用
类型正常的引用赋值SortReference类WeakReference类PhantomReference类
回收时间不回收内存紧张时回收Gc就回收随时可能被回收

五.垃圾收集算法

1.标记-清除算法
2.标记-复制算法
3.标记-整理算法
4.分代收集

1.标记-清除算法

  • 算法分为”标记“和”清除“两个阶段,为非移动式的回收算法。

  • 标记阶段: 标记出所有需要回收的对象。

  • 回收阶段: 统一回收所有被标记的对象。

  • 优点: 简单

  • 缺点: 效率不高,内存碎片

在这里插入图片描述

2.标记-复制算法

  • 半区复制: 将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。-当这一块的内存用完了,就将还存活着的对象复制到另外一块,上面-然后再把已使用过的内存空间一次清理掉。
  • 优点: 简单、高效。
  • 缺点: 可用内存减少、对象存活率高时复制操作较多。

在这里插入图片描述

3.标记-整理算法

  • 分为“标记”和“整理”两个过程,为移动式的回收算法。
  • 标记阶段: 与“标记-清除”算法一样。
  • 整理阶段: 让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存
  • 优点: 避免碎片产生,无需两块相同内存。
  • 缺点: 计算代价大,标记清除+碎片整理,更新引用地址。

在这里插入图片描述

4.分代收集 标记-清除算法

  • Java对象的生命周期不同,有长有短,根据对象存活周期,将内存划分新生代和老年代

  • 新生代(Young Generation) :主要存放短暂生命周期的对象。新创建的对象都先放入新生代,大部分新建对象在第一次gc时被回收.

  • 老年代(Tenured Generation) :一个对象经过几次gc仍存活,则放入老年代。这些对象可以活很长时间,或者伴随程序一生,需要常驻内存的,可以减少回收次数。

  • 针对各个年代特点采用适合的收集算法
    新生代: 复制算法
    在这里插入图片描述
    老年代: 标记-清除和标记-整理算法
    在这里插入图片描述
    图片都来源于网络

六.垃圾收集器

  • Serial收集器(复制算法): 新生代单线程收集器,标记和清理都是单线程,优点是简单高效;
  • ParNew收集器 (复制算法): 新生代收并行集器,实际上是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现;
  • Parallel Scavenge收集器 (复制算法): 新生代并行收集器,追求高吞吐量,高效利用 CPU。吞吐量 = 用户线程时间/(用户线程时间+GC线程时间),高吞吐量可以高效率的利用CPU时间,尽快完成程序的运算任务,适合后台应用等对交互相应要求不高的场景;
  • Serial Old收集器 (标记-整理算法): 老年代单线程收集器,Serial收集器的老年代版本;
  • Parallel Old收集器 (标记-整理算法): 老年代并行收集器,吞吐量优先,Parallel Scavenge收集器的老年代版本;
  • CMS(Concurrent Mark Sweep)收集器(标记-清除算法): 老年代并行收集器,以获取最短回收停顿时间为目标的收集器,具有高并发、低停顿的特点,追求最短GC回收停顿时间。
  • G1(Garbage First)收集器 (标记-整理算法): Java堆并行收集器,G1收集器是JDK1.7提供的一个新收集器,G1收集器基于“标记-整理”算法实现,也就是说不会产生内存碎片。此外,G1收集器不同于之前的收集器的一个重要特点是:G1回收的范围是整个Java堆(包括新生代,老年代),而前六种收集器回收的范围仅限于新生代或老年代。

参考文献:[1] 周志明.深入了解Java虚拟机[M].机械工业出版社,2020-:.71-82
,也可以观看陈良育老师的《Java核心技术(高阶)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天一个秃顶小技巧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值