关于javascript:内存泄漏-JavaScriptGC垃圾回收机制-springboot实战电商项目mall4j

39次阅读

共计 1652 个字符,预计需要花费 5 分钟才能阅读完成。

springboot 实战电商我的项目 mall4j(https://gitee.com/gz-yami/mall4j)

java 开源商城零碎

内存透露

什么是内存透露?

程序的运行须要内存。只有程序提出要求,操作系统或者运行时(runtime)就必须供应内存。对于继续运行的服务过程,必须及时开释不再用到的内存。否则,内存占用越来越高,轻则影响零碎性能,重则导致过程解体。

简略地说: 不再用到的内存,没有及时开释,就叫做内存透露(memory leak)

有一些语言(比方 C 语言)必须手动开释内存,即内存治理由程序员来负责,所有的内存都须要手动开释,想想就很繁琐,绝大多数的语言提供主动的内存治理,咱们称之为”垃圾回收机制“

JS 的垃圾回收机制 - 两种收集策略

垃圾收集机制原理:垃圾收集器会依照固定的工夫距离(或代码执行中预约的收集工夫),周期性地去找出那些不再持续应用的变量,而后开释其占用的内存。

1. 标记革除

标记革除(mark-and-sweep)是 JavaScript 中最重用的垃圾收集形式

当一个变量在应用时,垃圾收集会给变量增加标记为 进入环境 ,实践上来说进入环境中的变量,断然是不能被开释的,因为在环境中的的变量很大概率正在应用;

当一个变量来到环境时,垃圾收集会将变量标记为 来到环境 当变量被标记为此状态,在垃圾收集器定时执行时,就会开释掉对应的变量占用的内存

// 申明一个 加 1 的函数
function addOne(num){  
  // 垃圾收集 将 sum 标记为“进入环境”let sum += num
  // 垃圾收集 将 sum 标记为“来到环境”return sum
}
addOne(1)  // 输入 2

目前所有的古代浏览器简直都应用 标记革除 这种垃圾回收算法

2. 援用计数

援用计数是最高级的垃圾收集算法。此算法把“对象是否不再须要”简化定义为“对象有没有其余对象援用到它”。如果没有援用指向该对象(零援用),对象将被垃圾回收机制回收。

这种策略存在缺点:当产生循环援用时,计数永远不会归零

// 示例
function fn(){var ojb1 = {};
  var ojb2 = {};
  ojb1.aa = ojb2; // o 援用 o2
  ojb2.aa = ojb1; // o2 援用 o

  return "循环援用";
}
// 调用 fn
fn();

示例中 ojb1 和 ojb2 通过本身的属性相互援用对方,即它们的被援用此时都为 2

那么在援用计数这种策略下,obj1 和 obj2 将不会被开释,因为它们援用次数不为 0,所以此办法存在内存透露的危险

JS 中常见的内存透露

理解了垃圾回收机制,回到内存透露的问题,日常开发中有哪些状况容易造成内存透露呢?

全局变量

function fn() {
    bar1 = 'some text'; // 没有申明但间接赋值 实际上是全局变量 => window.bar1
    this.bar2 = 'some text' // 全局变量 => window.bar2
}
fn()

未革除的定时器

function fn() {setInterval(function() {var box = document.querySelector('#box');
        if(box) {box.innerHTML = JSON.stringify(serverData);
        }
    }, 5000); // 每 5 秒调用一次
}
fn()

事件监听

增加了事件监听但未移除

window.addEventListener('scroll', this.handleScroll)

闭包

var closure = function(){
    var count = 0;
    return function(){return count ++;}
}
const fn = closure(); 
console.log(fn()); // 0
console.log(fn()); // 1
console.log(fn()); // 2

每次调用 fn 时,count 值都基于上一次的值减少 1,即 count 的援用始终保留在内存中

springboot 实战电商我的项目 mall4j(https://gitee.com/gz-yami/mall4j)

java 开源商城零碎

正文完
 0