OpenLayers Ext.form.ComboBox存储查询会产生内存泄漏

时间:2015-02-21 16:50:29

标签: memory-leaks combobox openlayers geoserver jsonstore

确认。使用OpenLayers,我有一个Ext.form.ComboBox,它运行Ext.data.JsonStore的查询来访问~1 Gb的shapefile并返回结果表。然后,用户可以选择其中一个结果,并将地图缩放到该位置。

这很好用。但!使用ComboBox时,JVM大小会持续增长 - 内存泄漏? - Geoserver会抛出许多与以下内容相关的问题:

Caused by: java.io.IOException: Map failed
Caused by: java.lang.OutOfMemoryError: Map failed
ERROR [geotools.map] - Call MapContent dispose() to prevent memory leaks

我可以在大约一分钟之内运行ComboBox多达五次,然后一阵错误让Geoserver崩溃(例如,GetFeatureInfo没有返回任何结果,ComboBox查询返回空,粉红色瓷砖出现,编辑:和GWC停止制作新瓷砖!)。

我是否需要销毁()或清除商店或......?如何?思考??

GeoExt 1.1,OpenLayers 2.12.rc6,Ext 3.4,Ext 4.2.1.883,jquery-1.6,Geoserver 2.5,JDK i586 v7,Tomcat 7

代码:

THE QUERY:查找ComboBox&中键入的内容填充商店

Ext.onReady(function() {
Ext.override(Ext.form.ComboBox, {
    doQuery: function(q, forceAll) {
        console.log('queryTpl', this.queryTpl, q); 
        q = Ext.isEmpty(q) ? '' : q;
        var qe = {
            query: q,
            forceAll: forceAll,
            combo: this,
            cancel: false
        };
        if (this.fireEvent('beforequery', qe) === false || qe.cancel) {
            return false;
        }
        q = qe.query;
        forceAll = qe.forceAll;
        if (forceAll === true || (q.length >= this.minChars)) {
            if (this.lastQuery !== q) {
                this.lastQuery = q;
                if (this.mode == 'local') {
                    this.selectedIndex = -1;
                    if (forceAll) {
                        this.store.clearFilter();
                    } else {
                        this.store.filter(this.displayField, q);
                    }
                    this.onLoad();
                } else {
                    this.store.baseParams[this.queryParam] = this.queryTpl ? String.format(this.queryTpl, q) : q;
                    this.store.load({
                        params: this.getParams(q)
                    });
                    this.expand();
                }
            } else {
                this.selectedIndex = -1;
                this.onLoad();
            }
        }
    },
});
})

THE STORE

var dsm = new Ext.data.JsonStore({
remoteFilter: true,
autoLoad: false,
autoDestroy: true,  // doesn't appear to help
url: '../geoserver/workspace',  // generalized, not for public access
storeId: 'myStore2',
baseParams: {
    service: 'WFS',
    version: '1.1.0',
    request: 'GetFeature',
    typeName: 'MRDS_LUT',    // *shp in geoserver defined by var
    srsName: 'EPSG:4326',
    outputFormat: 'json',
    propertyName: 'SiteName,Municipal,Commodity,Status,Longitude,Latitude'
},
root: 'features',
fields: [{
    name: 'SiteName',
    mapping: 'properties.SiteName'
}, {
    name: 'Municipal',
    mapping: 'properties.Municipal'
}, {
    name: 'Commodity',
    mapping: 'properties.Commodity'
}, {
    name: 'Status',
    mapping: 'properties.Status'
}, {
    name: 'Longitude',
    mapping: 'properties.Longitude'
}, {
    name: 'Latitude',
    mapping: 'properties.Latitude'
},{
    name: 'bbox',
    mapping: 'properties.bbox'
}],
sortInfo: {
    field: "Municipal",
    direction: "ASC"
}
});

ComboBox

var panelSiteNameSearch = new Ext.form.ComboBox({
store: dsm,
fieldLabel: "<b>Search</b>",
queryParam: "cql_filter",
queryTpl: "SiteName Like '{0}%'",
minChars: 5,
displayField: "SiteName",
valueField: "SiteName",
typeAhead: false,
loadingText: "Searching...",
width: 230,
emptyText: "Mine/Mineral Site Search",
hideTrigger: true,
tpl: '<tpl for="."><div class="search-item"><b>Site Name:</b> {SiteName}<br><b>Commodity: </b> {Commodity}<br><b>Municipality:</b> {Municipal}<br><b>Status:</b> {Status}</div><hr/></tpl>',
itemSelector: "div.search-item",
    listeners: {
        "select": function (combo, record) {
            mrdsprimary.setVisibility(true);
            mrdssecondary.setVisibility(true);
            mrdstertiary.setVisibility(true);
            map.setCenter(new OpenLayers.LonLat(record.data.Longitude,record.data.Latitude),13);
        },
        "focus": function () {
            keyboardnav.deactivate();
        },
        "blur": function () {
            keyboardnav.activate();
        }
    }
});   

1 个答案:

答案 0 :(得分:0)

这个解决方案有点模糊。我最终通过确保所有组合框存储的总大小加上初始Java -Xms分配不超过Java -Xmx分配来防止内存不足错误。

例如,将-Xms设置为500m,并且知道存储#1访问600m的数据库而存储#2访问800m的数据库,在我的Java环境堆中总共提供了1900mb。如果-Xmx设置为2g,则不会抛出任何错误。

理论上。我不能直接影响Java环境的Xms而不会干扰(糟糕)Tomcat / Java的本机GC。知道总分配的-Xmx上限,以及直接对它有什么影响,鼓励非常精细的数据存储。

不幸的是我只限于一个32位的JDK i586,我读到的地方对-Xmx有一个固有的2gb限制(这似乎是正确的)。据报道,64位高得多。

调查结果:远程存储“加载”整个数据存储,并在本地提交过滤结果...使用removeAll或clearFilter或setValue()清除任一存储或NULL和/或SYNC仅在本地工作且实际上不存在触发任何远程GC或减少远程Java堆积不必要的存储。

长期解决方案:创建一个服务器端PHP脚本,将给定的cql或其他查询或ComboBox值直接传递给SQL或PostGIS数据库,并将javascript保留在其中。但我还不知道怎么写。