首页 > 编程知识 正文

gc垃圾回收机制原理,三种常规垃圾收集算法效率比较

时间:2023-05-03 11:32:58 阅读:15796 作者:4582

垃圾回收的对象主要是堆内存

Java为每个类型规定了具体的不变大小。 因此,所有内存都是由JVM自动分配的,所以所有内存的管理和回收都是由JVM自动执行的。

对象回收由垃圾收集器(Garbage Collector — GC )执行。 如果默认堆内存利用率超过70%,GC将启动。

为什么需要回收垃圾:

在程序运行期间,会生成一系列占用内存的代表性对象,并将它们存储在内存中。 一些对象在生命周期结束后仍会消耗部分内存。 占用这些内存但不重复使用的对象,我们称为“垃圾”。 而且,“垃圾”占有的存储器的回收就是垃圾回收。

4种垃圾回收算法:

(1)标记法)分为2个阶段(标记和清除)

标记阶段:遍历所有对象,并将活动对象的头部标记为活动

清除阶段:再次遍历对象,检查对象头部,对于没有活动标记的对象,释放其内存区域; 对于具有活动标记的对象,请取消标记

优点:算法简单,实现简单

缺点:

碎片:由于只删除垃圾对象而不处理生存对象,因此生存对象分布的不连续性将可用内存划分为块。 如果新对象请求内存,则需要访问内存。 哪些空闲块(链表可以用于保持空闲块的位置)可以充分满足该对象的需要。 在更极端情况下,空闲存储器的合计比对象请求的区域大,但是没有足够的连续空闲区域来完成存储器的分配

与写时复制技术不兼容:“写时复制”是优化内存使用和提高并行环境中的性能的重要思想。 滴滴涕,该技术在有写入时,复制内存,达到一定的优化目的。 另一方面,标记清除算法的标记过程是向存储器(对象报头)的一次写入,不断地引起存储器复制。 因此,标记清除算法与该技术不兼容

)引用计数)垃圾收集关注对未重用对象的垃圾收集。 换句话说,由垃圾收集清除的对象(存储器)不会被其他对象重新引用。 在中,可以为每个对象引入计数器,以便对于任何对象,只要有对该对象的引用,就将计数器加1。 结束对该对象的引用,使计数器递减1; 当计数器返回0时,表示可以清除此对象。 这就是引用计数法

缺点:

资源消耗:由于需要为每个对象维护计数器,因此每次更新指针时都会伴随计数器更新,从而在一定程度上消耗计算资源

内存使用量:计数器需要占用一定的内存,为了安全起见,计数器值的上限必须大于所有对象的上限,这也是不少开销

实现复杂:引用计数思想简单,但实现起来并不容易。 无法解决循环计数

循环计数:假设有两个对象a和b,a引用b对象,b也引用a对象。 在这种情况下,两个对象的引用计数器都不是0,但由于存在交叉引用,无法垃圾回收a和b,从而导致内存泄漏

(3)复制算法

在复制算法中,首先将内存分为From区域和To区域两部分,两部分的大小相等。 对象分配仅在来自区域中进行。 复制算法可以分为两个阶段。 第一步是类似于标签清除算法的标签,在From区域中找到所有活动对象。 区别是第二步。 复制算法将这些活动的对象,复制到To区,清空原From区全部,交换两个内存的职责。 也就是说,一旦更换GC,原来的From区变成To区,To区则相反

与标签清除算法相比,快速:复制算法在标记阶段只需要标记哪些对象处于活动状态,与标签清除算法需要遍历所有对象相比,性能更高

不发生碎片:同样,与标签移除算法相比,生存对象连续分配给待处理区域,因此不需要像标签移除算法那样维护碎片区域

分配速度快:由于不会发生碎片,因此新对象请求内存时,可以在分配时直接添加到From空间的已用内存之后,分配速度快

内存利用率低:对象的可用空间只是其他算法的一半,因为复制算法将内存分为两部分

递归复制单元格对象:对象通常与单元格对象相关联。 复制这些对象时,必须递归处理自身对象。 这通常会产生一定的开销。 另外,在递归调用的情况下,存在函数堆栈的消耗,潜在堆栈溢出的风险

(04 )垃圾分代回收机制

惠普空间

Young Generation (新生代) )。

伊甸园。

生存区域) )。

从空间

到空间

Old Generation (老生代) )。

Eden : Survivor=4 : 1

对象创建之初放入伊甸园,在伊甸园经过一次扫描后,如果该对线依然存在,则移动到生存区。 在生存区,如果该对象多次扫描仍存在,将被列入古生代。 老生代的扫描频率远远低于新生代。

对象在回收时扫描新生代,如果新生代释放的内存不足,则扫描古生代。

回收到新生代(第一代回收(minor gc ) ) ) ) ) ) ) )。

老一代回收—完全回收(全GC ) ) ) ) ) ) )。

**

扩展** :对象创建后,如果在伊甸园不能放弃,将启动第一代回收(minor gc );如果回收后不能放弃,将启动第二次第一代回收(minor gc );即使在第二次回收之后如果放入失败,则触发一次

完全回收(full gc),对象会再次试图放入新生代,如果放入失败则触发第三次初代回收(minor gc),回收之后试图放入新生代,如果放入失败,则再次试图放入老生代,如果放入失败,则触发第二次完全回收(full gc)。对象试图放入新生代,如果失败,则试图放入老生代,如果失败则抛出OutOfMemoryError — 内存溢出错误

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。