对垃圾回收的简单了解

1、垃圾回收本质

是靠运行环境额外做了很多工作,来完成自动释放内存的操作。

2、垃圾回收的劣势:

  1. 消耗额外的开销
  2. 可能会影响程序的流畅运行(经常会引入STW问题)

3、垃圾回收要回收什么?

主要回收堆,代码中大量的内存在堆上。

【注意】:GC不会出现"半个对象"的情况,对于这种一部分仍在使用,一部分不在使用的对象,整体来说是不释放的,等到这个对象彻底完全不使用,才真正的释放。主要还是为了让垃圾回收起来更方便,更简单。

垃圾回收的基本单位是"对象",而不是"字节"。

4、垃圾回收具体是怎么回收的?

1)、找垃圾/判定垃圾

如何找垃圾?

a、基于引用技术(不是Java中采取的方案)

针对每个对象都会额外引入一小块内存,保存这个对象有多少个引用指向他,每当有一个地方引用它时,计数器就+1;当引用失效时,计数器就-1;当引用计数为0的时候,就不在使用被释放了。

缺点:

  1. 空间利用率比较低,每个new的对象都得搭配计数器
  2. 会有循环引用的问题

b、基于可达性分析(Java中采取的方案)

通过额外的线程,定期的针对整个内存空间的对象进行扫描,有一些起始的位置(称为GCRoots),会类似于深度优先遍历一样,把可以访问的对象都标记一遍(带有标记的对象就是可达的对象),没被标记的对象就是不可达,就是垃圾。

GCRoots:

  • 1. 虚拟机栈(栈帧中的本地变量表)中引用的对象;
  • 2. 方法区中类静态属性引用的对象;
  • 3. 方法区中常量引用的对象;
  • 4. 本地方法栈中 JNI(Native方法)引用的对象。

可达性分析的优点:克服了引用计数的两个缺点:空间利用率低、循环引用

自身的缺点:系统开销大,遍历一次可能比较慢

找垃圾的核心就是确认这个对象未来是否还会使用,没有引用指向,就不使用了

2)、释放垃圾

a、标记-清除

标记就是可达性分析的过程;清除就是直接释放内存

此时如果直接释放内存,虽然内存是还给系统了,但是被释放的内存是离散的,带来的问题就是“内存碎片”

b、复制算法

"复制"算法是为了解决"标记-清理"的效率问题。它将可用内存按容量划分为大小相等的两块,每次只使 用其中的一块。当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后 再把已经使用过的内存区域一次清理掉。这样做的好处是每次都是对整个半区进行内存回收,内存分配 时也就不需要考虑内存碎片等复杂情况,只需要移动堆顶指针,按顺序分配即可。

c、标记-整理算法

复制收集算法在对象存活率较高时会进行比较多的复制操作,效率会变低。因此在老年代一般不能使用 复制算法。 针对老年代的特点,提出了一种称之为"标记-整理算法"。标记过程仍与"标记-清除"过程一致,但后续步 骤不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的 内存。

d、分代算法

分代算法和上面讲的 3 种算法不同,分代算法是通过区域划分,实现不同区域和不同的垃圾回收策略, 从而实现更好的垃圾回收。这就好比中国的一国两制方针一样,对于不同的情况和地域设置更符合当地 的规则,从而实现更好的管理,这就是分代算法的设计思想。

当前 JVM 垃圾收集都采用的是"分代收集(Generational Collection)"算法,这个算法并没有新思想,只 是根据对象存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代。在新生代中,每 次垃圾回收都有大批对象死去,只有少量存活,因此我们采用复制算法;而老年代中对象存活率高、没 有额外空间对它进行分配担保,就必须采用"标记-清理"或者"标记-整理"算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值