Java内存问题使用Apache.POI来读取Excel

时间:2016-01-18 08:26:29

标签: java memory-leaks apache-poi xssf

我正在尝试阅读excel文件...进行一些更改...保存到新文件。

我用按钮创建了小表单......按下按钮..

  • 它将加载Excel文件并将所有数据加载到我创建的类的数组列表中。
  • 它将遍历数组列表并更改对象中的少数属性。
  • 它会将数据保存到新的Excel文件中。
  • 最后,它将清除阵列列表并显示完成消息框。

现在问题是内存问题。
当窗体加载时,我可以在windows任务管理器中看到... javaw正在使用大约23MB。
在读写时优秀......内存拍摄高达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");
            }
        }
    };


此课程中的阅读/ 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。

2 个答案:

答案 0 :(得分:4)

您可能没有内存泄漏......

  

当加载表单时,我可以在windows任务管理器中看到... javaw是   使用大约23MB。在读写和写入期间...内存拍摄到了   170MB。清除数组列表后......内存未清除   保持在150MB左右。

这并没有描述内存泄漏 - 任务管理器向您显示进程保留的内存 - 而不是应用程序heap space

您的JVM会将堆分配到其配置的最大值,例如200 MiB。通常,在从OS分配此内存之后,JVM不会(通常)将其返回。但是,如果您查看堆使用情况(使用JConsole或JVisual VM之类的工具),您将看到在GC之后回收堆。

Java如何消耗内存

作为一个非常基本的例子:

JVisual VM Memory

图片来源:https://stopcoding.files.wordpress.com/2010/04/visualvm_hfcd4.png

在此示例中,JVM具有1 GiB最大堆,并且由于应用程序需要更多内存,因此从OS(橙色区域)保留了400 MiB。

蓝色区域是应用程序使用的实际堆内存。锯齿效应是垃圾收集过程回收未使用的内存的结果。请注意,橙色区域保持相当静态 - 通常不会因每个GC事件而调整大小......

  

在几秒钟内......它最多可拍摄800MB,并一直待到最后......我   没有任何内存错误

如果您有内存泄漏,最终会出现内存不足错误。 A&#34;泄漏&#34; (至少在Java中)是应用程序占用堆中的内存,但是没有释放它以供应用程序重用。如果您观察到的内存快速响应,但应用程序没有倒下,您可能会看到内部(在JVM中)内存实际上正在被释放和重用。

限制Java可以使用的内存(OS)

如果要限制应用程序可以从操作系统保留的内存,则需要配置最大堆大小(通过-Xmx选项)以及永久生成大小(如果您需要)仍在使用Java 7或更早版本)。请注意,JVM本身使用一些内存,因此OS级别(使用任务管理器等工具)显示的值可能高于您指定的应用程序内存总和。

答案 1 :(得分:0)

在新版本的poi中,他们使用Java流来解决内存问题。Have a look