JVM垃圾回收

1 如何判断对象可以回收

1.1引用计数法
通过统计这个对象被引用的数量,来判断是否可以被回收,但是当两个对象互相引用的时候,就判断不出这个对象是可以被回收的了, JVM虚拟机并没有使用这个回收方法
1.2 可达性分析算法(JVM使用)

如果一个对象被根对象直接或间件的引用,则这个对象不能被回收。否则则相反。

  • Java虚拟机中的垃圾回收采用可达性分析来探索所有存活的对象
  • 扫描堆中的对象,看是否能够沿着GC Root对象做为引用链找到该对象,找不到,表示可以回收
1.2.1Java中可以作为GC Roots的对象
  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(即一般说的native方法)中引用的对象
1.2.2 OopMap

HotSpot是才采用准确式垃圾收集,
当线程停顿下来收,并不需要一个不漏的检查完所有执行上下文和全局引用的位置, 虚拟机是有办法直接得到哪些位置存放对象的引用, 在HotSpot中采用OopMap的数据结构来实现
具体看这个链接:https://www.iteye.com/blog/dsxwjhf-2201685

1.2.3 安全点与安全区域

添加链接描述

1.3 四种引用
  1. 强引用 : 一般情况下,直接赋值的对象,就是强引用
  2. 软引用: GCRoot引用软引用, 然
  3. 弱引用: GCRoot引用弱引用, 然后弱引用 对象,当发生垃圾回收时,不管内存够不够,都会被回收
  4. 虚引用: 当虚引用引用的对象被垃圾回收时,虚引用对象就会被放入引用队列,然后有东西会扫描引用队列,然后释放虚引用所对应的那块直接内存
  5. 终结器引用: 当对象重新了finallize(),就会有终结器引用这点对象,当没有强引用的时候, 终结器引用就会被放入引用队列,

软引用和弱应用还可以配合引用队列使用()
虚引用和终结器引用必须配合引用队列使用
在这里插入图片描述

2.垃圾回收算法

2.1 标记清除

在这里插入图片描述

先对无引用的对象进行标记,然后再一起清除
优点: 速度快
缺点: 容易造成内存碎片

2.2标记整理

在这里插入图片描述
优点: 对内存碎片进行了整理, 确定: 因为对碎片进行了整理,所以更耗时了

2.3 标记复制算法
  1. 先标记,不被引用的对象,
  2. 把引用的对象,复制到新的一块内存中,
  3. 把原内存中的对象全部清空,
  4. 交换两块内存位置,让新内存变旧内存,旧内存变新内存

优点:不会产生碎片,缺点: 会占用双倍的内存空间

3.JVM 是通过协同三种算法来实现的(分代回收)


JVM 的GC回收是通过分代回收的方式来实现回收的,

1. 分为两大块 : 新生代和老年代。新生代又分为:伊甸园 ,幸存区From, 幸存区To

  1. 当new的对象都会放入伊甸园中, 当伊甸园的空间不够时, 新生代会进行一次垃圾回收,也就是Minor GC。minor gc会引发stop the world, 暂停其他用户的线程,等待垃圾回收结束,用户线程才恢复运行。
  2. 会进行一次标记复制算法, 把伊 甸园中 幸存的对象放入幸存区To中,并且存活下来的对象寿命加一。
  3. 然后幸存区To会与幸存区From进行交换, 当然数据实际的地址并不会改变, 而是交换指针来实现交换
  4. 当回收多次后,幸存区对象的寿命超过了一个阈值,这个超过阈值 的对象就会被放入到老年代中,最大寿命是15(4bit)。有时当新生代内存不足时,也会提前放入老年代中。
  5. 当老年代中内存满了并且新生代Minor GC后也放不下新对象时, 就会产生一次 Full GC。STW的时间更长
2 参数

在这里插入图片描述

4.记忆集和卡表

在分代回收的时候,会产生跨代引用的问题,就是老年代中的对象引用了新生代中的对象,如果这边被引用的新生代中的对象被回收了,就会发送问题 , 然后为了解决这个问题就在新生代中建立了一个叫记忆集(Rememberd Set)的数据结构,指向哪些被引用的新生代对象位置,让其不会被回收,解决了跨代引用的问题,
记忆集根据记录的精度分三类:
  • 字长精度:记录的是老年代指向新生代地址。
  • 对象精度:记录的是老年代引用的新生代对象。
  • 卡精度:记录的是新生代一段地址是否存在被老年代引用的记录。
    第三种卡精度也是选择最常用的, 也就是我们所称为的卡表(cart table),
    记忆集和卡表的关系: 就像是map和hashmap的关系一样, 记忆集是一个概念,而卡表是记忆集的具体实现。
    卡表就是一个字节数组,CART_TABLE[this address >> 9] = 0;
    这个数组中每个都可以看作一个特定大小的内存块,就是卡页(cart page) , 一般来说每个cart page不止一个对象, 但是一要一个卡页中有一个对象或更多个对象的字段存在着跨代指针的问题,这一页的标识就会变成1, 也就是所谓变脏(Dirty),然后扫描的时候把这块卡页一起加入GC Root 中扫描。要‘
4.2. 写屏障

写屏障是用来解决卡表的元素维护问题的,比如谁来把他们变脏,他们何时变脏。这里我还没做深入的了解。后面看了再写吧。

5. 垃圾回收器

在这里插入图片描述

1.串行
  • 单线程
  • 堆内存较小,适合个人电脑
2.吞吐量优先
  • 多线程
  • 堆内存较大,多核cpu
  • 尽可能让STW的时间最短
3.响应时间优先 (CMS)
  • 多线程
  • 堆内存较大,多核cpu
  • 尽可能让单次STW的时间最短
4.G1

定义: Garbage First

  • 2014 JDK9 默认
    适用场景
  • 同时注重吞吐量(Throughput)和低延迟(Low latency),默认的暂停目标是200ms
  • 超大堆内存,会将堆划分为多个大小相同的Region
  • 整体上是标记+整理算法,两个区域之间是复制算法

    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值