我从一个大型java脚本应用程序中的内存泄漏调查开始,该应用程序在基于webkit和sfx(java脚本核心引擎)的浏览器中作为小部件运行。过了一会儿,我发现内存的来源随着时间的推移而增加。碰巧是$.ajax(..)
。
好的,我想,让我们尝试不同版本的jquery
或直接使用XMLHttpRequest
- 同样的结果。然后我在谷歌浏览器上检查它并感到惊讶,因为堆分析器既没有显示js对象数量的增加也没有增加堆大小,而chrome任务管理器显示内存和私有内存增加。我测试的代码如下:
var Main = {};
var xhr = new XMLHttpRequest();
function makeRequest() {
xhr.timeout = 2000;
xhr.ontimeout = function() {
xhr.abort();
}
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
};
xhr.open("POST", "", true); //async post request to local server
xhr.send("{}");
}
Main.onLoad = function()
{
setInterval(function() { makeRequest(); }, 3000);
}
那么,这种行为可以吗?这不是本机内存泄漏的迹象吗?
P.S。我在Windows 7企业版上使用版本为35.0.1916.153的chrome。
答案 0 :(得分:2)
According to the spec,xhr不会自动GC。
4.2垃圾收集
如果状态为XMLHttpRequest对象,则不得对其进行垃圾回收 OPENED和send()标志置位,其状态为HEADERS_RECEIVED,或 其状态为LOADING,并且已注册一个或多个事件侦听器 其类型是readystatechange,progress,abort,error,load, 超时和loadend。
如果XMLHttpRequest对象在其连接时被垃圾收集 仍处于打开状态,用户代理必须终止请求。
This article对此问题和类似问题有很好的解释。通常的解决方法是在xhr = null
之后通过xhr.send()
清除回调中对宿主对象的引用。我说通常的修复,因为你没有分配更多的xhr对象或在这个例子中对结果做任何事情。如你所说,堆没有改变,看起来你没有泄漏。
单独使用chrome任务管理器无法告诉您是否有泄漏。我发现this article是一个有用的教程,介绍如何使用chrome的devtools来诊断内存泄漏。您需要手动触发GC并验证内存不会持续增长。如果您发现确实存在内存泄漏,则可以使用devtools来确定哪些对象不属于保留路径,但仍在内存中(有关如何在该文章中执行此操作的详细信息)。