[英]Java Memory issue using Apache.POI to read write Excel
我正在嘗試讀取Excel文件...進行一些更改...保存到新文件。
我已經創建了帶有按鈕的小表格。
現在的問題是內存問題。
加載表單后,我可以在Windows任務管理器中看到... javaw正在使用約23MB。
在讀寫excel期間...內存拍攝高達170MB。
清除陣列列表后...。內存沒有清除,並保持在150MB左右。
以下代碼附加到事件單擊按鈕。
MouseListener mouseListener = new MouseAdapter() {
public void mouseReleased(MouseEvent mouseEvent) {
if (SwingUtilities.isLeftMouseButton(mouseEvent)) {
ArrayList<Address> addresses = ExcelFunctions.getExcelData(fn);
for (Address address : addresses){
address.setZestimate(Integer.toString(rnd.nextInt(45000)));
address.setRedfinestimate(Integer.toString(rnd.nextInt(45000)));
}
ExcelFunctions.saveToExcel(ofn,addresses);
addresses.clear();
JOptionPane.showMessageDialog(null, "Done");
}
}
};
該類中Reading / Excel文件的代碼。
public class ExcelFunctions {
public static ArrayList<Address> getExcelData(String fn)
{
ArrayList<Address> output = new ArrayList<Address>();
try
{
FileInputStream file = new FileInputStream(new File(fn));
//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
System.out.println(sheet.getSheetName());
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
int r = row.getRowNum();
int fc= row.getFirstCellNum();
int lc = row.getLastCellNum();
String msg = "Row:"+ r +"FColumn:"+ fc + "LColumn"+lc;
System.out.println(msg);
if (row.getRowNum() > 0) {
Address add = new Address();
Cell c0 = row.getCell(0);
Cell c1 = row.getCell(1);
Cell c2 = row.getCell(2);
Cell c3 = row.getCell(3);
Cell c4 = row.getCell(4);
Cell c5 = row.getCell(5);
if (c0 != null){c0.setCellType(Cell.CELL_TYPE_STRING);add.setState(c0.toString());}
if (c1 != null){c1.setCellType(Cell.CELL_TYPE_STRING);add.setCity(c1.toString());}
if (c2 != null){c2.setCellType(Cell.CELL_TYPE_STRING);add.setZipcode(c2.toString());}
if (c3 != null){c3.setCellType(Cell.CELL_TYPE_STRING);add.setAddress(c3.getStringCellValue());}
if (c4 != null){c4.setCellType(Cell.CELL_TYPE_STRING);add.setZestimate(c4.getStringCellValue());}
if (c5 != null){c5.setCellType(Cell.CELL_TYPE_STRING);add.setRedfinestimate(c5.getStringCellValue());}
output.add(add);
c0=null;c1=null;c2=null;c3=null;c4=null;c5=null;
}
}
workbook.close();
file.close();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
return output;
}
public static void saveToExcel(String ofn, ArrayList<Address> addresses) {
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("Addresses");
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("State");
header.createCell(1).setCellValue("City");
header.createCell(2).setCellValue("Zip");
header.createCell(3).setCellValue("Address");
header.createCell(4).setCellValue("Zestimates");
header.createCell(5).setCellValue("Redfin Estimate");
int row = 1;
for (Address address : addresses){
Row dataRow = sheet.createRow(row);
dataRow.createCell(0).setCellValue(address.getState());
dataRow.createCell(1).setCellValue(address.getCity());
dataRow.createCell(2).setCellValue(address.getZipcode());
dataRow.createCell(3).setCellValue(address.getAddress());
dataRow.createCell(4).setCellValue(address.getZestimate());
dataRow.createCell(5).setCellValue(address.getRedfinestimate());
row++;
}
try {
FileOutputStream out = new FileOutputStream(new File(ofn));
workbook.write(out);
out.close();
workbook.close();
System.out.println("Excel with foumula cells written successfully");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}}
我無法弄清楚問題出在哪里。 我也關閉工作簿/輸入流/輸出流並清除Arraylist。
您可能沒有內存泄漏...
加載表單后,我可以在Windows任務管理器中看到... javaw正在使用約23MB。 在讀寫excel期間...內存拍攝高達170MB。 清除陣列列表后...。內存沒有清除,並保持在150MB左右。
這並不描述內存泄漏-任務管理器向您顯示進程保留的內存-而不是應用程序堆空間 。
您的JVM將最多分配堆,使其達到配置的最大值,例如200 MiB。 通常,從操作系統分配了此內存后,JVM不會(經常)將其退還給您。 但是,如果您查看堆的使用情況(使用諸如JConsole或JVisual VM之類的工具),則會看到在GC之后回收了堆。
Java如何消耗內存
作為一個非常基本的示例:
圖片來源: https : //stopcoding.files.wordpress.com/2010/04/visualvm_hfcd4.png
在此示例中,JVM的最大堆容量為1 GiB,並且由於應用程序需要更多內存,因此從OS(橙色區域)保留了400 MiB。
藍色區域是應用程序使用的實際堆內存。 鋸齒效應是垃圾回收過程回收未使用的內存的結果。 請注意,橙色區域保持相當靜態-通常不會隨着每個GC事件而調整大小...
在幾秒鍾之內...它可以拍攝高達800MB的內存,直到結束....我沒有出現任何內存錯誤
如果發生內存泄漏,最終將出現內存不足錯誤。 “泄漏”(至少在Java中)是指應用程序占用堆中的內存,但不釋放內存以供應用程序重用。 如果觀察到的內存迅速增加,但是應用程序沒有崩潰,則您可能會發現內部(在JVM中)內存實際上已被釋放和重用。
限制Java可以使用多少(OS)內存
如果要限制應用程序可以從OS保留的內存,則需要配置最大堆大小(通過-Xmx
選項)以及永久生成大小(如果仍在使用Java 7或更早版本)。 請注意,JVM本身會使用一些內存,因此在OS級別顯示的值(使用任務管理器之類的工具)可能會高於您指定的應用程序內存總和。
在新版本的poi中,他們使用Java流來解決內存問題。 看一看
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.