详谈各种语言的垃圾回收机制

无引用----垃圾

一.c/c++

1.引用计数算法

即计算被引用的次数。

特点:废弃即回收,每次在对象创建或者释放时都要计算引用数值。

缺点:无法处理环形引用。由于要计算次数,有额外的时间上的和空间上的成本。

2.标记-清除算法

即遍历所有存活对象,对其进行标记。

特点:可达保留,不可达清除。

缺点:遍历所有,开销大。

3.标记-缩并算法

即把幸存部分合并,自由单元排出去。

特点:结构灵活,根据不同的压缩算法压缩后的对象位置不同。

缺点:压缩算法选择不当可能会影响程序性能。

4.节点拷贝算法

即将堆分两区,将成活对象分到另一区。

特点:在拷贝过程中进行了内存整理。

缺点:两倍空间。

二.java(其GC与C++不同的是:自动分配内存和自动回收内存)

1.引用计数算法

每个对象实例都有一个引用计数器。

2.可达性算法

类似标记-清除算法,同样是判断其引用链是否可达。

3.复制算法

类似节点拷贝算法,将存活对象从对象面复制到空闲面。

4.分代回收算法

特点:按照对象生命周期的不同划分区域以采用不同的垃圾回收算法。有效提高了JVM的回收效率。

关于分代回收算法:分区如下

基本处理规则:将堆空间分为年轻代与老年代;

年轻代分为Eden区以及两个survival 区--From区和to区,默认的情况下它们的内存大小比例是8:1:1,也就是说如果新生代分配了100M空间,Eden区大小是80M,From区和to区各10M。

老年代是一个整块区域Tenured区,新生代和老年代的内存比例默认是1:2,也就是如果堆空间是300M,那么新生代是100M,老年代是200M。

但是为什么会提高JVM的效率呢??我马上找了一篇讲JVM的文章研究:

思考:

首先,我们知道:java有着优良的内存管理功能,在写代码时只需要考虑业务实践。大概率来讲,这一独特的GC回收机制是服务于内存管理的优化。

在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。而且我们知道,java中的堆是 JVM 所管理的最大的一块内存空间。

由此得出:为大量对象进行分区,选择合适的算法进行逐个击破,才是最适当的做法。

1.在新生代中,由于其对象的生命周期较短,每次手机都会有大批对象死去,而少量对象存活,对于这种较少的存活对象,我们选用复制算法单独把他拎出来就行。

2.老年代中与其恰好相反,且没有额外空间对其进行分配担保,采用标记的方法最大化节约空间。

3.还有一个晋升的机制,在我看来就是这个算法的最佳补丁:当Eden没有足够空间的时候就会触发jvm发起一次Minor GC,。如果对象经过一次Minor-GC还存活,并且又能被Survivor空间接受,那么将被移动到Survivor空间当中。并将其年龄设为1,对象在Survivor每熬过一次Minor GC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代中了,当然晋升老年代的年龄是可以设置的。

所以以下对象容易被晋升到老年代:

a.经历一定的Minor次数依然存活的对象。

b.Survivor区中存放不下的对象。

c.新生成的大对象.

4.Java的两类GC:

    1. Minor GC: 用来处理年轻代区域
    2. Full GC: 用来收集老年代区域。

三.js

对于js的GC机制,我们联系他的语言特色作单独讨论。

js的数据存储:js的引用数据类型是的引用数据类型是保存在堆内存中的,然后在栈内存中保存一个对堆内存中实际对象的引用。即栈存地址,堆存实际值(链表)。

具体情景:首先假设我们申明一个变量a,引用了对象b,然后我们把a赋值了一个数组对象,也就变成了该变量引用了一个数组,那么之前的对象引用关系就无了。对于之前那个无用的对象,我们自然要对它进行清理。

使用的GC算法:GC算法与之前提到的大同小异,对js而言,标记更为常用,我们可以从以下几个角度去分析:

1.js是一种动态类型的语言,变量的类型可以在运行时更改,生命周期是可变化的,标记算法可以实现对对象的有效跟踪。

2.自动内存管理:JavaScript是一种高级语言,开发人员无需手动分配和释放内存。标记-清除算法适合这种自动内存管理模型,因为它提供了一种无需程序员干预的内存管理方式。

3.垃圾回收与事件循环:JavaScript通常用于编写浏览器端和Node.js服务器端应用程序,这些应用程序通常涉及事件驱动的编程模型。标记-清除算法的延迟清理特性使得它能够与事件循环模型很好地集成,不会中断程序执行,确保了用户界面的响应性。

对于第三点,我们举一个简单的点击事件的例子来详细探讨:

  1. 用户点击按钮:当用户点击按钮时,浏览器会将点击事件添加到事件队列中,等待处理。
  2. 事件循循环开始:事件循环开始执行,它检查事件队列是否有待处理的事件。
  3. 事件处理程序执行:事件处理程序被触发,开始执行。在事件处理程序执行期间,可能会创建新的对象、变量、或者分配内存以存储数据。
  4. 内存分配:在事件处理程序中,可能会创建一些对象用于处理数据。这些对象在事件处理程序执行完成后仍然处于活动状态,因为它们被引用着。
  5. 标记-清除垃圾收集:在事件处理程序执行期间,标记-清除垃圾收集算法也在后台运行。它会标记当前仍然可达的对象(例如事件处理程序中的对象),但不会立即清除垃圾(只是标记为待清理)。这使得事件处理程序可以继续执行而不受垃圾收集的影响。
  6. 事件处理程序完成:事件处理程序成功完成并返回结果,将数据显示在网页上。
  7. 清除垃圾:在事件处理程序执行完成后,当浏览器检测到内存不足时,垃圾收集器会在事件循环的空闲时间(例如用户未执行其他操作)触发清除阶段,清理那些未被标记为可达的对象,释放它们占用的内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值