ExtJS4 内存泄漏

Posted

技术标签:

【中文标题】ExtJS4 内存泄漏【英文标题】:ExtJS4 memory leak 【发布时间】:2013-01-30 14:53:59 【问题描述】:

我有一个用 ExtJS 4.1.1 编写的应用程序,它经常使用一个存储。我从服务器获取数据样本,经过一些验证后,我使用其“添加”方法将其添加到存储中。我这样做 我会定期从商店中删除我不需要的记录。

问题是,随着时间的推移,我的应用程序正在消耗越来越多的 RAM,我似乎找到了问题的根源,但我不知道如何处理它。

这是我的商店定义:

this.store = Ext.create('Ext.data.Store', 
        fields: ['when', 'data1', 'data2', 'data3', 'data4', 'data5', 'data6', 'data7', 'data8', 'data9'],
        proxy: 
            type: 'memory',
            reader: 
                type: 'json',
                root: 'users'
            
        ,
        sorters: [
            property: 'when',
            direction: 'ASC'
        ]
    );

这就是我从中删除记录的方式:

var record = self.store.getAt(j);
if((record.get('when') <= newMinDate) && (record.get('data'+id) !==' ')) 
  self.store.remove(record);
  record.destroy();
  record = null;
  j--;
  ln--;

但是当我在调试这个问题时检查控制台时,我可以看到,记录实际上是从存储中删除的,而不是从内存中删除的。

编辑/更新: 我尝试使用您的答案中的建议来解决问题,但都无法解决。可以肯定的是,我得到了正确的问题源,我提取了我的商店代码以更仔细地检查它,看看它是否真的导致了问题。您可以在下面看到整个代码:

Ext.define('TestApp.App', 
extend: 'Ext.app.Application'
);

Ext.application(
extend: 'MyApp.app.Application',

store: null,

launch: function() 
    var self = this;
    self.store = Ext.create('Ext.data.Store', 
        fields: ['when', 'data1', 'data2', 'data3', 'data4', 'data5', 'data6', 'data7', 'data8', 'data9'],
        proxy: 
            type: 'memory'
        ,
        sorters: [
            property: 'when',
            direction: 'ASC'
        ]
    );
    self.beginTask();
,

beginTask: function() 
    var self = this;
    Ext.TaskManager.start(
        run: function() 
            var jsonRaw = *very large json*; //about 650 samples
            var json = Ext.JSON.decode(jsonRaw, true);
//                self.store.add(json.data.samples);
//                var ln = self.store.getCount();
//                for (var j=0; j<ln; j++) 
//                    var record = self.store.getAt(j);
//                    self.store.remove(self.store.getAt(j));
//                    j--;
//                    ln--;
//                    record.destroy();
//                    delete record;
//                
            json = null;
            jsonRaw = null;
        ,
        interval: 1000
    );

);

现在奇怪的部分是:即使存储部分像上面的代码清单一样被注释,内存泄漏仍然存在。我是不是在任务管理方面犯了一些错误?

【问题讨论】:

【参考方案1】:

我使用 Ext JS 发现的许多问题之一是 Ext.data.Model#destroy 实际上并没有在本地清理记录。 destroy 方法使用商店的代理发送对该记录的销毁请求(例如,如果您需要从数据库中删除相应的记录)。如果这是您的预期行为,那就不用担心。

当您从存储中删除记录时,该存储会在名为 removed 的数组中保留对该记录的引用。您可以在 Ext.data.Store#remove 方法的底部看到它。我建议使用 javascript 调试器并在删除几次后检查您的商店对象,以查看您的记录是否被缓存。如果是,只需调用store.removed.length = 0; 即可清除。

【讨论】:

我完全忘记了那个数组。 +1【参考方案2】:

如果您在删除后执行store.sync() 会发生什么?不知道这是否有助于内存代理,但我认为它应该删除对已删除记录的引用。只是对记录执行remove(record) 并不会真正删除该记录,它只是将其标记为删除,并停止将其公开为在商店中可用。至少对于其他代理类型是这样。只有在通过store.sync(); 同步了商店的修改记录(添加、删除、更新)后才能执行实际删除。这就是商店在其内部列表中保存新状态的记录的时候。

也许 sra 是正确的,而您自己在其他地方的闭包中持有对记录的引用?

【讨论】:

以上是关于ExtJS4 内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

MFC内存泄漏调试

如何防止java中的内存泄漏

记录一次DialogFragment 内存泄漏

常见的内存泄漏原因及解决方法

Android ValueAnimator --内存泄漏

Android内存泄漏查找和解决