Javascript的内存管理

翻译 2016年11月22日 16:16:34

原文地址


介绍

低级语言,像C语言具有能够进行内存管理的工具,比如malloc( )和free( ),另一方面,当一个变量被创建时,javascript的内存会自动分配,当变量不再使用时,也会自动释放。后面的这一过程被称为垃圾回收机制。这种垃圾回收机制是混乱管理的缘由,这给js(或其他高级语言)开发者带来他们能够不去关心内存是如何管理的感觉。这是错误的。


内存的生命周期

不论哪种编程语言,内存的生命周期都是相同的:
  1.  Allocate the memory you need  分配你需要的内存
  2. Use the allocated memory (read, write)  使用分配的内存(读和写)
  3. Release the allocated memory when it is not needed anymore  当你不需要时释放内存

第一二部分在所以语言都是显式的,最后一部分是在低级语言中是显式的,但是在高级语言中却是隐式的,比如JavaScript。


javascript中的内存分配:

1、值得初始化,为了减轻程序员的编程负担,js在分配的时候就声明了值。
2、由函数返回来分配。


使用变量:

使用变量基本上就是读和写分配的内存。我们读写变量的值或者是一个对象的属性,甚至可以传递一个参数给函数来处理。


当不需要的时候释放内存:

大多数内存管理的问题都出现在这个时候,这里最难的就是找到不再需要这块内存的那个时间。通常这都是由开发人员来确定程序中的哪块内存不再需要,并释放它。
高级语言都嵌入了垃圾回收机制,其工作原理是跟踪内存分配和使用,以便找到何时不再需要一块已分配的内存,在这种情况下,它将自动释放。这个过程只能是模糊的,因为程序一般不知道一块内存是否还需要,这是不可判断的(这不能由算法解决)。



垃圾回收机制



如上所述,普遍问题是自动去查找一块分配的内存是否不再需要这是不可判断的。垃圾回收机制实现了如何解决这个问题的限制。本节将帮助理解垃圾回收机制的原理以及局限性。


垃圾回收机制的算法依赖的是引用原理(the notion of reference.)。在内存管理的环境中,一个对象被看做是另一个对象的引用,如果前者对后者具有一个访问(显式或者隐式)。比如,js对象具有对其原型(隐式)和属性(显式)的引用。


这里所说的“对象”的概念扩展到比常规js对象更广泛,并且包含函数作用域(以及全局词法作用域)。


下面接受的是最原始的垃圾回收集算法。该算法将“一个对象不再被需要”定义为“一个对象没有引用它的其他对象”。如果一个对象有0个引用指向,则该对象被认为是可回收的。

var o = { 
  a: {
    b:2
  }
}; 
// 2 objects are created. One is referenced by the other as one of its properties.
// The other is referenced by virtue of being assigned to the 'o' variable.
// Obviously, none can be garbage-collected




var o2 = o; // the 'o2' variable is the second thing that 
            // has a reference to the object
o = 1;      // now, the object that was originally in 'o' has a unique reference
            // embodied by the 'o2' variable


var oa = o2.a; // reference to 'a' property of the object.
               // This object has now 2 references: one as a property, 
               // the other as the 'oa' variable


o2 = "yo"; // The object that was originally in 'o' has now zero
           // references to it. It can be garbage-collected.
           // However what was its 'a' property is still referenced by 
           // the 'oa' variable, so it cannot be freed


oa = null; // what was the 'a' property of the object originally in o 
           // has zero references to it. It can be garbage collected.




限制:循环

当该算法涉及到循环时,就会受到限制,下面的事例中,创建了两个对象并且相互引用,从而构建了一个循环。函数调用完毕后,它们讲不会离开函数作用域,所以他们实际上是没有作用的并且应该被释放。然而引用计数算法认为每个对象都被引用了一次,因此没有可以被垃圾回收的对象。

function f(){
  var o = {};
  var o2 = {};
  o.a = o2; // o references o2
  o2.a = o; // o2 references o


  return "azerty";
}


f();




真实的案例

在ie6、7中已知使用的是DOM对象的引用计数垃圾回收器。循环引用是一个常见的会产生内存泄漏的错误。



var div;
window.onload = function(){
  div = document.getElementById("myDivElement");
  div.circularReference = div;
  div.lotsOfData = new Array(10000).join("*");
};



在上面的示例中,DOM元素“myDivElement”在“circularReference”属性中具有对其自身的循环引用。如果该属性未被明确删除或清空,引用计数的垃圾回收器将始终有一个完整引用,并且将DOM元素保留在内存中,即使它已从DOM树中删除。如果DOM元素保存大量数据(在上面的示例中使用“lotsOfData”属性),则此数据消耗的内存永远不会被释放。


标记和扫描算法



该算法将“对象不再需要”定义归纳为“对象不可达”。
该算法假定知道一组被称为roots的对象(在js中root就是全局对象)。垃圾回收器将定期从这些roots开始查找,然后找到所有从这些roots引用的对象,和所有不被他们引用的对象。从roots开始,垃圾回收器将找到的所有可到达得对象并回收不可到达的对象。

该算法比之前的算法更好,因为“对象零引用”所认为的该对象不可达,相反我们已经看到了循环就知道这不是真的。

截至2012年,所有现代浏览器都装有一个标记清除垃圾回收器。在过去几年中,在JavaScript垃圾回收领域generational/incremental/concurrent/parallel garbage collection)中所做的所有改进都是该算法的实现改进,而不是垃圾回收算法本身的概念, 当“一个对象不再需要”。

循环不再是问题

在上面的第一个例子中,在函数调用返回之后,2个对象不再被从全局对象可达的东西引用。因此,它们将被垃圾回收器发现不可达。

第二个例子也是一样。一旦div和它的处理程序从根无法访问,它们都可以被垃圾回收,尽管引用彼此。

限制:对象需要明确无法访问

虽然这被标记为一个限制,这是一个很少在实践中达到的,这就是为什么没有人经常关心垃圾回收的原因。

javascript的垃圾回收机制与内存管理

一、垃圾回收机制—GC Javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存。 原理:垃圾收集器会...
  • OLiver_web
  • OLiver_web
  • 2016年12月31日 17:05
  • 2983

JavaScript是如何工作的:内存管理 + 如何处理4个常见的内存泄露

本系列第一篇重点介绍了引擎、运行时、调用栈。第二篇揭示了谷歌V8 JavaScript引擎的内部机制,并且提供了一些关于如何写出更好的JavaScript代码的建议。 本文作为第三篇,将会讨论另...
  • hj7jay
  • hj7jay
  • 2017年10月09日 09:18
  • 276

JavaScript 工作原理(一)——内存管理与四种常见内存泄漏的处理方法

几周前,我们新开了一系列文章,旨在深入 JavaScript,探寻其工作原理。我们认为通过了解 JavaScript 的构建方式和其运行规则,我们能写出更好的代码和应用。 第一篇文章重点介绍了引...
  • tangxiaolang101
  • tangxiaolang101
  • 2017年09月27日 15:59
  • 326

JavaScript内存管理机制

JavaScript解释器的内存管理机制:当定义变量时为其分配一部分内存空间,当不再使用这个变量时就会自动释放这部分内存空间,即垃圾回收(garbage collection)。 这种机制使我...
  • rsylqc
  • rsylqc
  • 2016年03月10日 02:39
  • 382

OS内存淘汰算法

1,LRU(Least Recently Used,最少最近使用算法) 计时法:给页表中的每一页增加一个域,专门用来存放计时标志,用来记录该页面自上次被访问以来所经历的时间。页面每被访问一次,计时清...
  • jinnlxl
  • jinnlxl
  • 2015年01月08日 17:30
  • 814

Linux内存管理浅析(一)

1.Linux内存管理的主要内容 a.      虚拟内存管理 b.      内核空间内存管理 c.      用户空间内存管理 2.虚拟内存和物理内存映射 ZONE_HIGH...
  • u012398362
  • u012398362
  • 2016年11月27日 19:40
  • 1010

深入浅出Linux内核内存管理基础

1 背景知识 1.1 用户空间与内核空间内存的划分        从Linux操作系统层次上,内存可划分为用户空间内存和内核空间内存。        32位的CPU,最大寻址范围为2^32 - 1也就...
  • acs713
  • acs713
  • 2015年01月18日 16:45
  • 4195

iOS 内存管理基本原则

我们知道objc中创建对象是存放在堆中的(基本数据类型除外,是由系统自己管理,并存放在栈中),系统不会自动释放堆中的内存。如果创建完的对象存放在堆中后并使用完没有得到及时的释放,会占用的内存。但是ob...
  • aaaa99996666
  • aaaa99996666
  • 2016年05月07日 19:33
  • 1730

操作系统:内存管理(概念)

对于计算机系统而言,操作系统充当着基石的作用,它是连接计算机底层硬件与上层应用软件的桥梁,控制其他程序的运行,并且管理系统相关资源,同时提供配套的系统软件支持。对于专业的程序员而言,掌握一定的操作系统...
  • oMengLiShuiXiang1234
  • oMengLiShuiXiang1234
  • 2016年05月30日 14:06
  • 8674

linux(arm架构)内存管理学习(1)

在研究内核hibernate实现的时候,由于需要对内存管理如MMU配置、内存分布和分配有相应了解,因此进行了专门的学习。最终结果是hibernate未研究出什么成果,反倒是内存管理的学习小有心得,就此...
  • alien75
  • alien75
  • 2016年08月31日 11:11
  • 1058
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Javascript的内存管理
举报原因:
原因补充:

(最多只允许输入30个字)