【问题标题】:heap size error from ArrayList来自 ArrayList 的堆大小错误
【发布时间】:2015-01-19 12:50:05
【问题描述】:

我有一节课

package com.firstgroup.bbrailapps.pushport.timetable;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;


/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;choice maxOccurs="unbounded" minOccurs="2">
 *           &lt;element ref="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}OR"/>
 *           &lt;element ref="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}IP"/>
 *           &lt;element ref="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}DT"/>
 *           &lt;element ref="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}PP"/>
 *         &lt;/choice>
 *         &lt;element ref="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}AS" maxOccurs="unbounded" minOccurs="0"/>
 *       &lt;/sequence>
 *       &lt;attribute name="rid" use="required" type="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}RIDType" />
 *       &lt;attribute name="uid" type="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}UIDType" />
 *       &lt;attribute name="ssd" use="required" type="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}RTTIDateType" />
 *       &lt;attribute name="trainId" type="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}TrainIdType" />
 *       &lt;attribute name="toc" type="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}TOCType" />
 *       &lt;attribute name="qtrain" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
 *       &lt;attribute name="status" use="required" type="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}CIFTrainStatusType" />
 *       &lt;attribute name="trainCat" use="required" type="{http://www.thalesgroup.com/rtti/XmlTimetable/v7/rttiCTTSchema.xsd}CIFTrainCategoryType" />
 *       &lt;attribute name="deleted" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
 *       &lt;attribute name="can" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "orOrIPOrDT",
    "as"
})
@XmlRootElement(name = "Journey")
public class Journey {

    @XmlElements({
        @XmlElement(name = "OR", type = OR.class),
        @XmlElement(name = "PP", type = PP.class),
        @XmlElement(name = "IP", type = IP.class),
        @XmlElement(name = "DT", type = DT.class)
    })
    protected List<Object> orOrIPOrDT;
    @XmlElement(name = "AS")
    protected List<AS> as;
    @XmlAttribute(required = true)
    protected String rid;
    @XmlAttribute
    protected String uid;
    @XmlAttribute(required = true)
    protected String ssd;
    @XmlAttribute
    protected String trainId;
    @XmlAttribute
    protected String toc;
    @XmlAttribute
    protected Boolean qtrain;
    @XmlAttribute(required = true)
    protected String status;
    @XmlAttribute(required = true)
    protected String trainCat;
    @XmlAttribute
    protected Boolean deleted;
    @XmlAttribute
    protected Boolean can;

    /**
     * Gets the value of the orOrIPOrDT property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the orOrIPOrDT property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getOROrIPOrDT().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link OR }
     * {@link PP }
     * {@link IP }
     * {@link DT }
     * 
     * 
     */
    public List<Object> getOROrIPOrDT() {
        if (orOrIPOrDT == null) {
            orOrIPOrDT = new ArrayList<Object>();
        }
        return this.orOrIPOrDT;
    }

    /**
     * Gets the value of the as property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the as property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getAS().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link AS }
     * 
     * 
     */
    public List<AS> getAS() {
        if (as == null) {
            as = new ArrayList<AS>();
        }
        return this.as;
    }

    /**
     * Gets the value of the rid property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getRid() {
        return rid;
    }

    /**
     * Sets the value of the rid property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setRid(String value) {
        this.rid = value;
    }

    /**
     * Gets the value of the uid property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getUid() {
        return uid;
    }

    /**
     * Sets the value of the uid property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setUid(String value) {
        this.uid = value;
    }

    /**
     * Gets the value of the ssd property.
     * 
     * @return
     *     possible object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public String getSsd() {
        return ssd;
    }

    /**
     * Sets the value of the ssd property.
     * 
     * @param value
     *     allowed object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public void setSsd(String value) {
        this.ssd = value;
    }

    /**
     * Gets the value of the trainId property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getTrainId() {
        return trainId;
    }

    /**
     * Sets the value of the trainId property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setTrainId(String value) {
        this.trainId = value;
    }

    /**
     * Gets the value of the toc property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getToc() {
        return toc;
    }

    /**
     * Sets the value of the toc property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setToc(String value) {
        this.toc = value;
    }

    /**
     * Gets the value of the qtrain property.
     * 
     * @return
     *     possible object is
     *     {@link Boolean }
     *     
     */
    public Boolean isQtrain() {
            return qtrain;
    }

    /**
     * Sets the value of the qtrain property.
     * 
     * @param value
     *     allowed object is
     *     {@link Boolean }
     *     
     */
    public void setQtrain(Boolean value) {
        this.qtrain = value;
    }

    /**
     * Gets the value of the status property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getStatus() {
        return status;
    }

    /**
     * Sets the value of the status property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setStatus(String value) {
        this.status = value;
    }

    /**
     * Gets the value of the trainCat property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getTrainCat() {
        return trainCat;
    }

    /**
     * Sets the value of the trainCat property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setTrainCat(String value) {
        this.trainCat = value;
    }

    /**
     * Gets the value of the deleted property.
     * 
     * @return
     *     possible object is
     *     {@link Boolean }
     *     
     */
    public Boolean isDeleted() {
            return deleted;
    }

    /**
     * Sets the value of the deleted property.
     * 
     * @param value
     *     allowed object is
     *     {@link Boolean }
     *     
     */
    public void setDeleted(Boolean value) {
        this.deleted = value;
    }

    /**
     * Gets the value of the can property.
     * 
     * @return
     *     possible object is
     *     {@link Boolean }
     *     
     */
    public Boolean isCan() {
            return can;
    }

    /**
     * Sets the value of the can property.
     * 
     * @param value
     *     allowed object is
     *     {@link Boolean }
     *     
     */
    public void setCan(Boolean value) {
        this.can = value;
    }

}

当我在数组列表中添加大约 60,000 个旅程类对象时。它给出了 java.lang.outofmemory 错误,我已将最大大小增加到 1GB 的堆大小。对于大元素,除了 ArrayList 之外还有其他选择吗?

【问题讨论】:

  • 你能发布你加载它的方式吗?
  • ArrayList 不太可能是您的问题。不过,在实例化时适当调整 ArrayList 的大小会有所帮助。
  • 我读取了一个 xml 文件,然后将元素添加到 arraylist。私有列表 lstJourney = new ArrayList(); public void endElement(String uri, String localName, String qName) throws SAXException { // logger.info("END element "+qName); if (qName.equalsIgnoreCase("Journey")) { // printJourney(journey); lstJourney.add(旅程); } }
  • 嗨,Brett,我给它的实例化大小是 50k,但同样的问题。
  • 你可以使用萨克斯以外的东西吗?原因 Sax 在处理之前将整个文件加载到内存中。如果可能的话,你可能会尝试类似blog.bdoughan.com/2012/08/…

标签: java arraylist out-of-memory heap-size


【解决方案1】:

ArrayList 本身可能不是问题;它更有可能中断,因为ArrayList 当您添加的元素多于当前数组可以包含的元素时分配了两倍的数组大小,即当内部元素数组已满时,它将使数组加倍并复制所有内容。所以在短时间内,它需要size()*3 倍的内存(实际数字略有不同,但你明白了)。

您可以使用其他列表,但它们需要更多内存,但需要小块。

上述错误还取决于每个Journey 对象的大小。 60K 个对象并不算多,但如果每个对象都是 10KB,那么这需要 600 MB 或您提供给 Java VM 的 1GB 的 60%。

解决方法:

  1. 不要将整个对象保存在 RAM 中,而是记住文件中的开始和结束位置。这只需要几个字节。当有人请求对象时,使用RandomFileAccess 仅读取单程的 XML 并对其进行解析。

  2. 不是将所有对象都保存在内存中,而是将数据放入数据库中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    • 2020-07-09
    • 1970-01-01
    相关资源
    最近更新 更多