内存泄漏JavaScript-GC垃圾回收机制-springboot实战电商项⽬mall4j
内存泄漏
什么是内存泄漏?
程序的运⾏需要内存。只要程序提出要求,操作系统或者运⾏时(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,所以此⽅法存在内存泄漏的风险
springboot推荐算法
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的引⽤⼀直保存在内存中