【发布时间】:2016-02-04 17:55:13
【问题描述】:
我在处理大文件时总是遇到堆内存问题。这里我正在处理 9 GB xml 文件。
这是我的代码。
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
InputStream in = new FileInputStream(sourcePath);
XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
Map<String, Cmt> mapCmt = new ConcurrentHashMap<String, Cmt>();
while (eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();
if (event.isStartElement()) {
//some processing and assigning value to map
Cmt cmt = new Cmt();
//get attributes
cmt.setDetails(attribute.getValue());
mapCmt.put(someKey,cmt);
}
}
一段时间后,我在迭代中遇到堆内存问题。 请帮我写优化代码。
注意:服务器有 3 GB 的可用堆空间。我无法增加服务器空间。 我正在使用以下参数执行 - -Xms1024m -Xmx3g
我的 xml 看起来像这样。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DatosAbonados xmlns="http://www.cnmc.es/DatosAbonados">
<DatosAbonado Operacion="1" FechaExtraccion="2015-10-08">
<Titular>
<PersonaJuridica DocIdentificacionJuridica="A84619488" RazonSocial="HERMANOS ROJAS" NombreComercial="PINTURAS ROJAS"/>
</Titular>
<Domicilio Escalera=" " Piso=" " Puerta=" " TipoVia="AVENIDA" NombreVia="MANOTERAS" NumeroCalle="10" Portal=" " CodigoPostal="28050" Poblacion="Madrid" Provincia="28"/>
<NumeracionAbonado>
<Rangos NumeroDesde="211188600" NumeroHasta="211188699" ConsentimientoGuias-Consulta="1" VentaDirecta-Publicidad="1" ModoPago="1">
<Operador RazonSocial="11888 SERVICIO CONSULTA TELEFONICA S.A." DocIdentificacionJuridica="A83519389"/>
</Rangos>
</NumeracionAbonado>
</DatosAbonado>
<DatosAbonado Operacion="1" FechaExtraccion="2015-10-08">
<Titular>
<PersonaJuridica DocIdentificacionJuridica="A84619489" RazonSocial="HERMANOS RUBIO" NombreComercial="RUBIO PELUQUERIAS"/>
</Titular>
<Domicilio Escalera=" " Piso=" " Puerta=" " TipoVia="AVENIDA" NombreVia="BURGOS" NumeroCalle="18" Portal=" " CodigoPostal="28036" Poblacion="Madrid" Provincia="28"/>
<NumeracionAbonado>
<Rangos NumeroDesde="211186000" NumeroHasta="211186099" ConsentimientoGuias-Consulta="1" VentaDirecta-Publicidad="1" ModoPago="1">
<Operador RazonSocial="11888 SERVICIO CONSULTA TELEFONICA S.A." DocIdentificacionJuridica="A83519389"/>
</Rangos>
</NumeracionAbonado>
</DatosAbonado>
</DatosAbonados>
我的 Cmt 课程是:
public class Cmt {
private List<DetailInfo> details;
public List<DetailInfo> getDetails() {
return details;
}
public void setDetails(DetailInfo detail) {
if(details == null){
details = new ArrayList<DetailInfo>();
}
this.details.add(detail);
}
}
实际上 Cmt 对象非常少,但我有 DetailInfo 对象 每个元素。如此巨大的不。 DetailInfo 对象是 已创建。
我的逻辑是这样的:
if (startElement.getName().getLocalPart().equals("DatosAbonado")) {
detailInfo = new DetailInfo();
Iterator<Attribute> attributes = startElement.getAttributes();
while (attributes.hasNext()) {
Attribute attribute = attributes.next();
if(attribute.getName().toString().equals("Operacion")){
detailInfo.setOperacion(attribute.getValue());
}
}
}
if (event.isEndElement()) {
EndElement endElement = event.asEndElement();
if (endElement.getName().getLocalPart().equals("DatosAbonado")) {
Cmt cmt = null;
if(mapCmt.keySet().contains(identificador)){
cmt = mapCmt.get(identificador);
} else{
cmt = new Cmt();
}
cmt.setDetails(detailInfo);
mapCmt.put(identificador, cmt);
}
}
【问题讨论】:
-
在这个过程中你创建了多少
Cmt对象?可能太多,无法容纳您的可用内存...... -
你没有显示全部:
attribute来自哪里?您在 mapCmt 中存储了多少个 Cmt 对象,它们有多大?此外,为每个起始元素事件创建一个 Cmt 似乎很奇怪。 -
@laune 这里我写了一些伪代码。创建的 Cmt 对象非常少,但 Cmt 对象包含为每个
创建的另一个对象的列表。 -
@wero 我在这里写了一些伪代码。创建的 Cmt 对象非常少,但 Cmt 对象包含为每个
创建的另一个对象的列表。 -
如果您要发布有关 DatosAbonado 的确切详细信息以及您在存储的 List 元素中存储的内容,您可能会提出建议。 XML 似乎非常多余,即两个
<DatosAbonado>有很多共同点。这将导致内存的巨大浪费。即使是 String.intern 也可能会减少内存。