Помогите с советом, как победить java.lang.OutOfMemoryException: java heap space.
ОЗУ на ПК 8ГБ, и делал настройки -Xms7G, никак не проходить. Главное на МасBook при 8ГБ норм работает.
Суть такова, что загружаю с формы xlsx около 9000 строк, валится как раз на методе XSSFSheet.read. Если в этом файле оставить строк 5, то все ок.
сам метод загрузки создает объект каждой строки.
rateClass = new RateClass(разные параметры, около 10 штук);
if (!mapOfRates.containsValue(rateClass)) {
mapOfRates.put(i, rateClass);
i++;
}
rateClass = null;
Может кто-то сможешь подсказать, почему так(( На более мощной машине, где 16Гб озу и core i7 все нормально работает.
@Service
@Component
public class GetListOfRatesImpl implements GetList {
// Подключаем логгер
private static Logger logger = LoggerFactory.getLogger(GetListOfRatesImpl.class);
// Основаная мапа, куда записываем все маршруты
private Map<Integer, RateClass> mapOfRates = new HashMap<>();
// Переменные для работы с файлами
private File file;
private FileInputStream fileInputStream;
// Переменные для работы с Excel файлом(формат XLSX)
private XSSFWorkbook xssfWorkbook;
private XSSFSheet sheet;
RateClass rateClass = null;
private GetListOfRatesImpl() {
}
@Override
public void fillMap() {
mapOfRates.clear();
// Получаем файл формата xls
try {
fileInputStream = new FileInputStream(this.file);
xssfWorkbook = new XSSFWorkbook(fileInputStream);
// Заполняем Map данными
sheet = xssfWorkbook.getSheetAt(0);
int i = 0;
for (int j = 1; j < sheet.getLastRowNum() + 1; j++) {
XSSFRow row = sheet.getRow(0);
String nameOfStationDeparture = null;
String nameOfStationDestination = null;
String customer = null;
double rate = 0.00d;
Date dateLoading = null;
String nameCargo = null;
String keyCargo = null;
for (int c = 0; c < row.getLastCellNum(); c++) {
if (row.getCell(c).getStringCellValue().trim().equals(JavaHelperBase.RATE_NAME_STATION_DEPARTURE)) {
XSSFRow xssfRow = sheet.getRow(j);
nameOfStationDeparture = xssfRow.getCell(c).getStringCellValue();
}
if (row.getCell(c).getStringCellValue().trim().equals(JavaHelperBase.RATE_NAME_STATION_DESTINATION)) {
XSSFRow xssfRow = sheet.getRow(j);
nameOfStationDestination = xssfRow.getCell(c).getStringCellValue();
}
if (row.getCell(c).getStringCellValue().trim().equals(JavaHelperBase.RATE_CUSTOMER)) {
XSSFRow xssfRow = sheet.getRow(j);
customer = xssfRow.getCell(c).getStringCellValue();
}
if (row.getCell(c).getStringCellValue().trim().equals(JavaHelperBase.RATE_NAME_CARGO)) {
XSSFRow xssfRow = sheet.getRow(j);
nameCargo = xssfRow.getCell(c).getStringCellValue();
}
if (row.getCell(c).getStringCellValue().trim().equals(JavaHelperBase.RATE_KEY_CARGO)) {
XSSFRow xssfRow = sheet.getRow(j);
if (xssfRow.getCell(c).getCellTypeEnum().equals(CellType.NUMERIC)) {
String val = Double.toString(xssfRow.getCell(c).getNumericCellValue());
double valueDouble = xssfRow.getCell(c).getNumericCellValue();
if ((valueDouble - (int) valueDouble) * 1000 == 0) {
val = (int) valueDouble + "";
}
keyCargo = val;
} else {
keyCargo = xssfRow.getCell(c).getStringCellValue();
}
}
if (row.getCell(c).getStringCellValue().trim().equals(JavaHelperBase.RATE_RATE)) {
XSSFRow xssfRow = sheet.getRow(j);
rate = xssfRow.getCell(c).getNumericCellValue();
}
if (row.getCell(c).getStringCellValue().trim().equals(JavaHelperBase.RATE_DATE_LOADING)) {
XSSFRow xssfRow = sheet.getRow(j);
dateLoading = xssfRow.getCell(c).getDateCellValue();
dateLoading.setHours(0);
dateLoading.setMinutes(0);
dateLoading.setSeconds(0);
if (dateLoading == null) dateLoading = new Date();
}
}
rateClass = new RateClass(nameOfStationDeparture, nameOfStationDestination, customer, nameCargo, keyCargo, rate, dateLoading);
if (!mapOfRates.containsValue(rateClass)) {
mapOfRates.put(i, rateClass);
i++;
}
rateClass = null;
}
logger.debug("Body rates: {}", mapOfRates);
} catch (IOException e) {
logger.error("Ошибка загруки файла - {}", e.getMessage());
} catch (OLE2NotOfficeXmlFileException e1) {
logger.error("Некорректный формат файла заявок, необходим формат xlsx");
}
}
public Map<Integer, RateClass> getMapOfRates() {
return mapOfRates;
}
public void setMapOfRates(Map<Integer, RateClass> mapOfRates) {
this.mapOfRates = mapOfRates;
}
public void setFile(File file) {
this.file = file;
fillMap();
}
}
RateClass
public class RateClass implements Comparable<RateClass> {
// Подключаем логгер
private static Logger logger = LoggerFactory.getLogger(Route.class);
private String nameOfStationDeparture; // Станция отправления
private String nameOfStationDestination; // Станция назначения
private String customer; // Заказчик
private CargoClass cargo; // Груз
private double rate; // Ставка
private Date loadingDate; // Дата погрузки
public RateClass(String nameOfStationDeparture, String nameOfStationDestination, String customer, String nameCargo, String keyCargo, double rate, Date loadingDate) {
this.nameOfStationDeparture = nameOfStationDeparture;
this.nameOfStationDestination = nameOfStationDestination;
this.customer = customer;
this.cargo = new CargoClass(nameCargo, keyCargo);
this.rate = rate;
this.loadingDate = loadingDate;
}
public String getNameOfStationDeparture() {
return nameOfStationDeparture;
}
public void setNameOfStationDeparture(String nameOfStationDeparture) {
this.nameOfStationDeparture = nameOfStationDeparture;
}
public String getNameOfStationDestination() {
return nameOfStationDestination;
}
public void setNameOfStationDestination(String nameOfStationDestination) {
this.nameOfStationDestination = nameOfStationDestination;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public CargoClass getCargo() {
return cargo;
}
public void setCargo(CargoClass cargo) {
this.cargo = cargo;
}
public double getRate() {
return rate;
}
public void setRate(double rate) {
this.rate = rate;
}
public Date getLoadingDate() {
return loadingDate;
}
public void setLoadingDate(Date loadingDate) {
this.loadingDate = loadingDate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RateClass rateClass = (RateClass) o;
return Double.compare(rateClass.rate, rate) == 0 &&
Objects.equals(nameOfStationDeparture, rateClass.nameOfStationDeparture) &&
Objects.equals(nameOfStationDestination, rateClass.nameOfStationDestination) &&
Objects.equals(customer, rateClass.customer) &&
Objects.equals(cargo, rateClass.cargo) &&
Objects.equals(loadingDate, rateClass.loadingDate);
}
@Override
public int hashCode() {
return Objects.hash(nameOfStationDeparture, nameOfStationDestination, customer, cargo, rate, loadingDate);
}
@Override
public String toString() {
return "RateClass{" +
"nameOfStationDeparture='" + nameOfStationDeparture + '\'' +
", nameOfStationDestination='" + nameOfStationDestination + '\'' +
", customer='" + customer + '\'' +
", cargo=" + cargo +
", rate=" + rate +
", loadingDate=" + loadingDate +
'}';
}
@Override
public int compareTo(RateClass o) {
return o.loadingDate.compareTo(this.loadingDate);
}
}
Стек ошибки
java.lang.OutOfMemoryError: Java heap space
com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.createChunk(Unknown Source)
com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.ensureCapacity(Unknown Source)
com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.createNode(Unknown Source)
com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.createDeferredAttribute(Unknown Source)
com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.setDeferredAttribute(Unknown Source)
com.sun.org.apache.xerces.internal.parsers.AbstractDOMParser.startElement(Unknown Source)
com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
org.apache.poi.util.DocumentHelper.readDocument(DocumentHelper.java:140)
org.apache.poi.POIXMLTypeLoader.parse(POIXMLTypeLoader.java:163)
org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument$Factory.parse(Unknown Source)
org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:226)
org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:218)
org.apache.poi.xssf.usermodel.XSSFWorkbook.parseSheet(XSSFWorkbook.java:443)
org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:408)
org.apache.poi.POIXMLDocument.load(POIXMLDocument.java:169)
org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:300)
com.uraltranscom.dynamicdistributionpark.service.impl.GetListOfRatesImpl.fillMap(GetListOfRatesImpl.java:72)
com.uraltranscom.dynamicdistributionpark.service.impl.GetListOfRatesImpl.setFile(GetListOfRatesImpl.java:158)
com.uraltranscom.dynamicdistributionpark.controller.Controller.routeList(Controller.java:51)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
Не могу уловить зачем используется i
, может быть достаточно списка вместо private Map<Integer, RateClass> mapOfRates = new HashMap<>();
или просто метод должен вернуть например: public List<RateClass> getRateClass()
или public Set<RateClass> getRateClass()
?
Можно считывать сразу файл XSSFWorkbook xssfWorkbook = new XSSFWorkbook(file);
Можно удалить все поля в сервисе они особо не нужны
Кстати каждый getRow
может создавать новый Integer
если отличен от промежутка -128 - 127
@Override
public XSSFRow getRow(int rownum) {
// Performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory
final Integer rownumI = Integer.valueOf(rownum); // NOSONAR
return _rows.get(rownumI);
}
Вынести в переменную XSSFRow xssfRow = sheet.getRow(j);
выше цикла?
Вынести все переменные тем самым избежать создания лишних объектов например:
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service;
import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List;
@Service public class GetListOfRatesImpl implements GetList {
private static Logger logger = LoggerFactory.getLogger(GetListOfRatesImpl.class);
@Override
public List<RateClass> getRateClass(File file) {
// Получаем файл формата xls
List<RateClass> rateClasses = new ArrayList<>();
try {
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(file);
XSSFSheet sheet = xssfWorkbook.getSheetAt(0);
XSSFRow row = sheet.getRow(0);
for (int j = 1; j < sheet.getLastRowNum() + 1; j++) {
XSSFRow xssfRow = sheet.getRow(j);
String nameOfStationDeparture = null;
String nameOfStationDestination = null;
String customer = null;
double rate = 0.00d;
Date dateLoading = null;
String nameCargo = null;
String keyCargo = null;
for (int c = 0; c < row.getLastCellNum(); c++) {
String headerCell = row.getCell(c).getStringCellValue().trim();
XSSFCell cell = xssfRow.getCell(c);
if (headerCell.equals(JavaHelperBase.RATE_NAME_STATION_DEPARTURE)) {
nameOfStationDeparture = cell.getStringCellValue();
}
if (headerCell.equals(JavaHelperBase.RATE_NAME_STATION_DESTINATION)) {
nameOfStationDestination = cell.getStringCellValue();
}
if (headerCell.equals(JavaHelperBase.RATE_CUSTOMER)) {
customer = cell.getStringCellValue();
}
if (headerCell.equals(JavaHelperBase.RATE_NAME_CARGO)) {
nameCargo = cell.getStringCellValue();
}
if (headerCell.equals(JavaHelperBase.RATE_KEY_CARGO)) {
if (cell.getCellTypeEnum().equals(CellType.NUMERIC)) {
Double numericCellValue = cell.getNumericCellValue();
keyCargo = numericCellValue.intValue() + "";
} else {
keyCargo = cell.getStringCellValue();
}
}
if (headerCell.equals(JavaHelperBase.RATE_RATE)) {
rate = cell.getNumericCellValue();
}
if (headerCell.equals(JavaHelperBase.RATE_DATE_LOADING)) {
dateLoading = cell.getDateCellValue();
dateLoading.setHours(0);
dateLoading.setMinutes(0);
dateLoading.setSeconds(0);
if (dateLoading == null) dateLoading = new Date();
}
}
rateClasses.add(new RateClass(nameOfStationDeparture, nameOfStationDestination, customer, nameCargo, keyCargo, rate, dateLoading);)
}
} catch (IOException | InvalidFormatException e) {
logger.error("Ошибка загруки файла - {}", e.getMessage());
} catch (OLE2NotOfficeXmlFileException e1) {
logger.error("Некорректный формат файла заявок, необходим формат xlsx");
}
logger.debug("Body rates: {}", rateClasses);
return rateClasses;
}
}
keyCargo как то сложно? два раза cell.getNumericCellValue()
if (headerCell.equals(JavaHelperBase.RATE_KEY_CARGO)) {
if (cell.getCellTypeEnum().equals(CellType.NUMERIC)) {
Double numericCellValue = cell.getNumericCellValue();
keyCargo = numericCellValue.intValue() + "";
} else {
keyCargo = cell.getStringCellValue();
}
}
Кстати если хип дамп есть то в нем должно быть понятно каких объектов много и на чем можно сэкономить
Причину нашел, оказалась проблема на машине, переустановил JVM и все заработало, спасибо всем.
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
В программе имеются коричневые квадраты слева(кнопки активации настроек) при нажатии на квадрат, из него выкатывается прямоугольник такого...
Делаю шифрование с помощью сдвигов битов в байтеНо если байту присвоить значение больше 127, оно начинает терять данные
Пишу телеграмм бота вылетает ошибка: