共计 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 开源商城零碎