我试图编写一个存在内存泄漏的 javascript 代码,以便在 Chrome 中使用分析器。但是,探查器似乎没有显示它应该显示的内容。
这是我的代码:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="start_button">Start</button>
<button id="destroy_button">Destroy</button>
<script type="text/javascript" charset="utf-8">
var Leaker = function(){};
Leaker.prototype = {
init:function(){
this._interval = null;
this.start();
},
start: function(){
var self = this;
this._interval = setInterval(function(){ self.onInterval(); }, 100);
},
onInterval: function(){ console.log("Interval"); }
};
$("#start_button").click(function(){
if(leak !== null && leak !== undefined){
return;
}
leak = new Leaker();
leak.init();
});
$("#destroy_button").click(function(){
leak = null;
});
var leak;
</script>
当我单击开始按钮时,您可以看到创建了一个新对象 Leaker。 当我点击销毁时,该对象被设置为空(注意:但它不会被垃圾收集,因为 setInterval 仍然有效)。
问题:但是,当我使用 Google Chrome Profiler 时,在我点击 destroy 后它没有显示任何对我的 Leaker 实例的引用(但它应该显示这样的引用,因为我在上面注意到,来自 setInterval 的闭包仍然保留着它)。
点击销毁按钮后的探查器(你可以看到我再也找不到泄漏者实例,而它应该在那里)。
这里是控制台,setInterval 仍在运行,尽管分析器向我们显示不再有 Leaker 实例。
我是否遗漏了垃圾收集工作方式或 Chrome 分析器的某些内容?
最佳答案
这两个分析器的区别在于,在您“销毁”leak
之前,Leaker 变量是全局变量,而在它之后则不是。所以它只是分析器(和 javascript 引擎)不按照你描述的方式工作。基本上,您可以看到全局变量,但看不到局部范围的变量。我想根据范围进行不同的分配是有意义的。在将泄漏设置为 null 之前,它需要对其他脚本可用。
您可以通过一个最小示例了解分析器如何根据范围以不同方式工作:
var Leaker = function() {};
var Leaker2 = function() {};
// this one is going to be in the profiler
var leak = new Leaker();
(function(){
// this one is not in the profiler
var leak2 = new Leaker2();
setInterval(function(){console.log(leak2)}, 500);
})()
编辑:
澄清一下,该对象仍在分析器中,并且仍在分配,但与全局对象不同。我只是创建了一个关于 Chrome 分析器如何工作的最小示例。当变量是全局变量时,您会在其中看到它并可以在类过滤器中对其进行过滤,但如果不是,则不能。
现在,它显然还在某个地方。你可以检查关闭下拉列表,你会看到你在两个快照上都有一个泄漏者:
也许在闭包中会创建一个副本,这样也可以分配上下文信息。
关于javascript - Chrome Profiler Javascript 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31673604/