在谈论垃圾牵开器之前,您需要澄清一些概念。JavaScript是一种薄弱的动态语言类型。
JavaScript数据类型:
在理解上述概率之后,首先提出一个问题:
猜猜上述两种方法执行后分别打印了什么?执行方法show1,明显打印的值,执行方法show2,printed。为什么?基本类型。方法show2中声明的A和B变量是对象,它是参考类型,因此差异应在此处。要充分理解这一点,您需要知道如何首先将变量存储在JavaScript中的存储空间中。
要了解在运行过程中如何存储JavaScript代码,我们必须首先找出存储空间的类型:
如下所示:
代码空间将在随后的文章中说明,本文将不参与。
堆栈空间在上一篇文章中反复提及,该文章用于存储上下文。首先回顾堆栈空间如何存储上下文的上下文,并查看以下代码:
在编译代码后,遇到函数调用后,将在堆栈空间中创建上下文,然后将其执行顺序执行。调用Show方法时,将在堆栈空间中生成上下文。如下图所示,存储了显示方法中声明的变量:
从图可以看出,当代码执行到变量B时,判断为b语句的变量是参考类型。JavaScript声明,堆栈空间中不存在参考类型的可变参考类型,而是在堆栈空间中,存储空间中的存储桩空间在存储空间中。它将生成一个地址,然后写下地址为变量B的值B。当还执行d = b时,D的变量值存储在地址堆中,如图::::::
从图中可以看出,B和D存储了堆积空间中堆空间的参考地址。B和D指向堆中的相同地址空间。因此,这里解释了。在B.NAME的审查值开始时,也将遵循更改。
在这一点上,我们知道堆栈空间存储的基本类型,并且堆栈空间存储在参考类型中。删除参考类型变量将在堆中打开一个空间以进行存储,并在堆中生成一个地址。堆栈空间的相应值只是堆地址,等同于进行运输。
了解堆栈空间和堆积空间存储过程,然后查看以下文章JavaScript执行机制2(更深的闭合)。我相信,对关闭的深度理解将有一个深入的理解。
以上部分是关于如何存储变量的。基本类型存储在堆栈空间中。参考类型存储在堆空间中。如果在分配空间后不再使用该变量,则将这些声明变量变为。存储器中的垃圾数据未回收。随着程序的运行,内存中将有大量垃圾邮件数据。记忆所占据的内存越大,不可避免地会导致口吃问题。步骤,它们如何回收。
仍然先看一下段落,如下所示:
上面的代码,呼叫显示方法,将生成一个显示执行上下文,输入呼叫堆栈,在上下文的变量环境中有两个变量。A是基本类型变量。存储值为1。b是一个参考类型variablethe存储值是堆空间中的地址。当调用显示示例方法时,创建了显示的表演的执行上下文。在可变环境中,C存储2和D存储与桩空间相对应的地址。如下所示:
执行显示功能时,将创建显示屏的执行上下文。同时,将会有一个,指向执行上下文的当前执行。显示:
因此,在执行上下文完成后,JavaScript将通过移动ESP向下方法来破坏内存中函数的执行上下文。
堆积空间中的回收策略比堆栈空间回收策略要复杂得多。在上面的示例中,当指针向下移至全局执行的上下文时,示威和显示的执行被上下销毁,并回收相应的内存空间,B和D,B和D,真实数据存储在堆积空间尚未回收,如下:
在上图中,当ESP指向全局执行的上下文时,堆栈空间中其他执行上下文所占据的空间已被回收,但是堆积空间1003和1005中的变量仍存储在内存中。对于内存回收,存储在堆空间中,涉及垃圾回收。
在V8中,它分为两个领域:新一代和旧一代:
无论主要垃圾回收的回收机制或边线垃圾回收器的回收机制,它们都具有相同的过程:
辅助垃圾回收设备和二次垃圾恢复设备主要负责新一代垃圾的恢复。通常将其分配给一些短而短的生存时间。尽管新一代中的记忆空间并不大,但恢复频繁。
辅助垃圾回收的算法是该算法,该算法将对象分为两个空间,一个是对象区域(也称为分配空间,分配空间),另一个是自由区域(也称为自由区域)幸存者空间,幸存者SAPCE)。分为两个相同大小的空间,如下:
创建新对象时,内存将分配在对象空间中。当空间满足时,将执行垃圾回收。使用简单的副本算法。首先,标记了活动对象和非活动对象。并以有序的方式订购这些对象等同于内存饰面,因此复制到自由空间后没有内存片段。
副本结束后,对象空间中的所有非活动对象都清晰。目前,对象空间和空闲空间进行了调整。操作,角色翻转可以在新一代的两个区域无限地重复使用。
如前所述,新一代的空间仅为1-8m。这是因为使用的复制操作。如果内存占据很大的内存,并且需要大量时间来复制,则新一代的内存设置较少。JavaScript使用促销策略:
主垃圾回收设备主垃圾回收设备负责旧一代的垃圾回收。对于大多数占据较大空间和长期生存时间的物体,它将被分配到旧一代空间。它需要很长时间并生存了很长时间。回复系统所需的时间将相对较长,并且操作效率不高。因此,主垃圾回收使用算法进行垃圾回收。简而言之,标记扫描算法是合理的。垃圾回收已穿越活跃的物体并将其标记为生存。在扫荡阶段,回收器横穿整个堆,然后回收未签名的区域。
在空闲链接列表中,Mark-Sweep使用链接列表来维护所有空闲空间。此链接列表被称为。当内存管理器需要申请内存时,您可以查询此链接列表,找到合适的自由块,然后分配空闲块,然后从空闲链接的列表中删除它。如果空格块很大,则,有必要将空闲块分开,部分进行分割,其余部分被重新添加到空闲链接列表中。如图所示:
在图中,A,C,D和F是空间中的活动对象。B,E,G是三个自由区。假设B的大小为20,E的大小为36,而G的大小为60。它们是免费的链接列表。自加州管理。有两个分配的请求需要分配30个空间,因此空间需要为分开满足,如下所示:
E空间的大小为36,满足分配要求。分布后,E的剩余空间很小。配电设备不再将其添加回免费的链接列表。因此,E和F之间存在一个记忆片段。第二请求分配在G区域中。分布完成后,G的剩余空间相对较大。因此,分销商将放置拆分空间,即H挂回空闲链接列表。上图中的分布完成的最终结果。
Mark-Sweep标签阶段(Mark)完成了空闲链接列表,然后说Mark-S-sweep从第一阶段开始,即标记阶段。商标阶段的核心任务是。我们需要记录活动活动对象在遍历遍历时,遍历方法采用了两种策略:BFS和DFS。在完成遍历后,找到了所有活动对象。:
从数字可以看出,当执行显示器时,ESP指针向下移动,并且上下文指向Show的执行。目前,通话堆栈已遍历。如果找不到1003的参考地址,则将标记此地址。1005此数据由B引用,并标记为活动对象。因此,如何标记活动对象?有两种常见方法:
在扫描阶段,即垃圾对象所占据的空间以恢复并将其放回空闲的链接列表中,扫除扫描阶段被删除。要结束从头到尾扫描整个空间的所有对象。以下图标只需显示恢复过程,如图所示:
从图可以看出,在清除标记后,将在堆空间中生成大量不连续的内存片段,并且这些内存片段将导致大对象无法分配连续的存储空间。。
就像标记算法中的标记算法一样,标记算法中的标记算法相同。如下:
这只是如何标记整理的过程。实际上,基础算法非常复杂。如果您有兴趣,您可以理解。G1 GC的分区回收算法可能是含义。该地区类型是:伊甸园,幸存者,古老,庞大,每个区域都可以分开管理。具体是复杂的,因此我在这里不会谈论它。
早期的Mark-sweep算法(SWT)早期的Mark-sweep算法将在订单屏幕上停止业务线程,将发生这种情况,称这种情况或(开始世界)。为了解决由垃圾恢复引起的垃圾问题,它是后来使用。V8将标记过程分为一个一个。同时,JavaScript代码和垃圾回收标记是交替的,直到完成标记为止。如下所示:
使用增量标记算法,可以将完整的垃圾回收任务分为几个小任务。每个任务需要短时间,这些任务插入了JavaScript代码中间,以避免完整停顿。
本文开始讲述变量是如何存储在内存中的。基本类型存在于堆栈空间中,并且参考类型存在于堆空间中。
在堆栈空间垃圾恢复中,JavaScript将通过向下移动ESP通过向下移动内存中的函数的执行上下文。如果在堆空间地址中引用了回收的执行上下文,则存储在堆空间中的对象将标记为垃圾数据。
桩恢复机制分为两部分,新一代和旧一代:
对于其他语言(例如Java)的垃圾回收商,可能存在类似的规格。Java还使用Mark Sweep,新一代的旧代表等,但是垃圾回收涉及世代相传的垃圾回收算法,交叉代用参考,出价算法等。在V8的垃圾回收率之间存在一定的差异。如果您有兴趣,您可以自己理解。
原始:https://juejin.cn/post/7099370331025965093