将大数据写入 Excel 工作表时出现 Java 堆空间错误、OutofMemory 异常

发布于 2024-10-26 12:39:52 字数 6782 浏览 2 评论 0原文

我在将大量数据从数据库写入 Excel 工作表时遇到 Java 堆空间错误。 我不想使用 JVM -XMX 选项来增加内存。

详细信息如下:

1) 我正在使用 org.apache.poi.hssf api 用于 Excel 表格编写。

2)JDK版本1.5

3)Tomcat 6.0

我编写的代码对于大约 23000 条记录运行良好,但对于超过 23K 条记录则失败。

以下是代码:

ArrayList l_objAllTBMList= new ArrayList();
    l_objAllTBMList = (ArrayList) m_objFreqCvrgDAO.fetchAllTBMUsers(p_strUserTerritoryId);
    ArrayList l_objDocList = new ArrayList();
    m_objTotalDocDtlsInDVL= new HashMap();
    Object l_objTBMRecord[] = null;
    Object l_objVstdDocRecord[] = null;
    int l_intDocLstSize=0;
    VisitedDoctorsVO l_objVisitedDoctorsVO=null;
    int l_tbmListSize=l_objAllTBMList.size();
    System.out.println(" getMissedDocDtlsList_NSM ");

        for(int i=0; i<l_tbmListSize;i++)
        {
            l_objTBMRecord = (Object[]) l_objAllTBMList.get(i);

            l_objDocList = (ArrayList) m_objGenerateVisitdDocsReportDAO.fetchAllDocDtlsInDVL_NSM((String) l_objTBMRecord[1], p_divCode, (String) l_objTBMRecord[2], p_startDt, p_endDt, p_planType, p_LMSValue, p_CycleId, p_finYrId);
            l_intDocLstSize=l_objDocList.size();
            try {
                    l_objVOFactoryForDoctors = new VOFactory(l_intDocLstSize, VisitedDoctorsVO.class); 

/* Factory class written to create and maintain limited no of Value Objects (VOs)*/

                } catch (ClassNotFoundException ex) {
                    m_objLogger.debug("DEBUG:getMissedDocDtlsList_NSM :Exception:"+ex);
                } catch (InstantiationException ex) {
                    m_objLogger.debug("DEBUG:getMissedDocDtlsList_NSM :Exception:"+ex);
                } catch (IllegalAccessException ex) {
                    m_objLogger.debug("DEBUG:getMissedDocDtlsList_NSM :Exception:"+ex);
                }


                for(int j=0; j<l_intDocLstSize;j++)
                {
                    l_objVstdDocRecord = (Object[]) l_objDocList.get(j);
                    l_objVisitedDoctorsVO = (VisitedDoctorsVO) l_objVOFactoryForDoctors.getVo();
                    if (((String) l_objVstdDocRecord[6]).equalsIgnoreCase("-"))
                    {
                        if (String.valueOf(l_objVstdDocRecord[2]) != "null")
                        {
                            l_objVisitedDoctorsVO.setPotential_score(String.valueOf(l_objVstdDocRecord[2]));
                            l_objVisitedDoctorsVO.setEmpcode((String) l_objTBMRecord[1]);
                            l_objVisitedDoctorsVO.setEmpname((String) l_objTBMRecord[0]);
                            l_objVisitedDoctorsVO.setDoctorid((String) l_objVstdDocRecord[1]);
                            l_objVisitedDoctorsVO.setDr_name((String) l_objVstdDocRecord[4] + " " + (String) l_objVstdDocRecord[5]);
                            l_objVisitedDoctorsVO.setDoctor_potential((String) l_objVstdDocRecord[3]);
                            l_objVisitedDoctorsVO.setSpeciality((String) l_objVstdDocRecord[7]);
                            l_objVisitedDoctorsVO.setActualpractice((String) l_objVstdDocRecord[8]);

                            l_objVisitedDoctorsVO.setLastmet("-");
                            l_objVisitedDoctorsVO.setPreviousmet("-");
                            m_objTotalDocDtlsInDVL.put((String) l_objVstdDocRecord[1], l_objVisitedDoctorsVO);
                        }

                    }

                }// End of While
               writeExcelSheet(); // Pasting this method at the end

            // Clean up code
            l_objVOFactoryForDoctors.resetFactory(); 
            m_objTotalDocDtlsInDVL.clear();// Clear the used map
            l_objDocList=null;
            l_objTBMRecord=null;
            l_objVstdDocRecord=null;

        }// End of While
        l_objAllTBMList=null;
        m_objTotalDocDtlsInDVL=null;

-------------------------------------------------------------------
private void writeExcelSheet() throws IOException
 {
        HSSFRow l_objRow = null;
        HSSFCell l_objCell = null;
        VisitedDoctorsVO l_objVisitedDoctorsVO = null;
        Iterator l_itrDocMap = m_objTotalDocDtlsInDVL.keySet().iterator();
        while (l_itrDocMap.hasNext())
        {
            Object key = l_itrDocMap.next();
            l_objVisitedDoctorsVO = (VisitedDoctorsVO) m_objTotalDocDtlsInDVL.get(key);
            l_objRow = m_objSheet.createRow(m_iRowCount++);

            l_objCell = l_objRow.createCell(0);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(String.valueOf(l_intSrNo++));

            l_objCell = l_objRow.createCell(1);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getEmpname() + " (" + l_objVisitedDoctorsVO.getEmpcode() + ")"); // TBM Name

            l_objCell = l_objRow.createCell(2);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getDr_name());// Doc Name

            l_objCell = l_objRow.createCell(3);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getPotential_score());// Freq potential score

            l_objCell = l_objRow.createCell(4);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getDoctor_potential());// Freq potential score

            l_objCell = l_objRow.createCell(5);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getSpeciality());//CP_GP_SPL

            l_objCell = l_objRow.createCell(6);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getActualpractice());// Actual practise

            l_objCell = l_objRow.createCell(7);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getPreviousmet());// Lastmet

            l_objCell = l_objRow.createCell(8);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getLastmet());// Previousmet

        }
        // Write OutPut Stream
        try {
                out = new FileOutputStream(m_objFile);
                outBf = new BufferedOutputStream(out);
                m_objWorkBook.write(outBf);
            } catch (Exception ioe) {
            ioe.printStackTrace();
            System.out.println(" Exception in chunk write");
        } finally {
            if (outBf != null) {
                outBf.flush();
                outBf.close();
                out.close();

                l_objRow=null;
                l_objCell=null;
            }

        }


    }

I am getting Java Heap Space Error while writing large data from database to an excel sheet.
I dont want to use JVM -XMX options to increase memory.

Following are the details:

1) I am using org.apache.poi.hssf api
for excel sheet writing.

2) JDK version 1.5

3) Tomcat 6.0

Code i have wriiten works well for around 23 thousand records, but it fails for more than 23K records.

Following is the code:

ArrayList l_objAllTBMList= new ArrayList();
    l_objAllTBMList = (ArrayList) m_objFreqCvrgDAO.fetchAllTBMUsers(p_strUserTerritoryId);
    ArrayList l_objDocList = new ArrayList();
    m_objTotalDocDtlsInDVL= new HashMap();
    Object l_objTBMRecord[] = null;
    Object l_objVstdDocRecord[] = null;
    int l_intDocLstSize=0;
    VisitedDoctorsVO l_objVisitedDoctorsVO=null;
    int l_tbmListSize=l_objAllTBMList.size();
    System.out.println(" getMissedDocDtlsList_NSM ");

        for(int i=0; i<l_tbmListSize;i++)
        {
            l_objTBMRecord = (Object[]) l_objAllTBMList.get(i);

            l_objDocList = (ArrayList) m_objGenerateVisitdDocsReportDAO.fetchAllDocDtlsInDVL_NSM((String) l_objTBMRecord[1], p_divCode, (String) l_objTBMRecord[2], p_startDt, p_endDt, p_planType, p_LMSValue, p_CycleId, p_finYrId);
            l_intDocLstSize=l_objDocList.size();
            try {
                    l_objVOFactoryForDoctors = new VOFactory(l_intDocLstSize, VisitedDoctorsVO.class); 

/* Factory class written to create and maintain limited no of Value Objects (VOs)*/

                } catch (ClassNotFoundException ex) {
                    m_objLogger.debug("DEBUG:getMissedDocDtlsList_NSM :Exception:"+ex);
                } catch (InstantiationException ex) {
                    m_objLogger.debug("DEBUG:getMissedDocDtlsList_NSM :Exception:"+ex);
                } catch (IllegalAccessException ex) {
                    m_objLogger.debug("DEBUG:getMissedDocDtlsList_NSM :Exception:"+ex);
                }


                for(int j=0; j<l_intDocLstSize;j++)
                {
                    l_objVstdDocRecord = (Object[]) l_objDocList.get(j);
                    l_objVisitedDoctorsVO = (VisitedDoctorsVO) l_objVOFactoryForDoctors.getVo();
                    if (((String) l_objVstdDocRecord[6]).equalsIgnoreCase("-"))
                    {
                        if (String.valueOf(l_objVstdDocRecord[2]) != "null")
                        {
                            l_objVisitedDoctorsVO.setPotential_score(String.valueOf(l_objVstdDocRecord[2]));
                            l_objVisitedDoctorsVO.setEmpcode((String) l_objTBMRecord[1]);
                            l_objVisitedDoctorsVO.setEmpname((String) l_objTBMRecord[0]);
                            l_objVisitedDoctorsVO.setDoctorid((String) l_objVstdDocRecord[1]);
                            l_objVisitedDoctorsVO.setDr_name((String) l_objVstdDocRecord[4] + " " + (String) l_objVstdDocRecord[5]);
                            l_objVisitedDoctorsVO.setDoctor_potential((String) l_objVstdDocRecord[3]);
                            l_objVisitedDoctorsVO.setSpeciality((String) l_objVstdDocRecord[7]);
                            l_objVisitedDoctorsVO.setActualpractice((String) l_objVstdDocRecord[8]);

                            l_objVisitedDoctorsVO.setLastmet("-");
                            l_objVisitedDoctorsVO.setPreviousmet("-");
                            m_objTotalDocDtlsInDVL.put((String) l_objVstdDocRecord[1], l_objVisitedDoctorsVO);
                        }

                    }

                }// End of While
               writeExcelSheet(); // Pasting this method at the end

            // Clean up code
            l_objVOFactoryForDoctors.resetFactory(); 
            m_objTotalDocDtlsInDVL.clear();// Clear the used map
            l_objDocList=null;
            l_objTBMRecord=null;
            l_objVstdDocRecord=null;

        }// End of While
        l_objAllTBMList=null;
        m_objTotalDocDtlsInDVL=null;

-------------------------------------------------------------------
private void writeExcelSheet() throws IOException
 {
        HSSFRow l_objRow = null;
        HSSFCell l_objCell = null;
        VisitedDoctorsVO l_objVisitedDoctorsVO = null;
        Iterator l_itrDocMap = m_objTotalDocDtlsInDVL.keySet().iterator();
        while (l_itrDocMap.hasNext())
        {
            Object key = l_itrDocMap.next();
            l_objVisitedDoctorsVO = (VisitedDoctorsVO) m_objTotalDocDtlsInDVL.get(key);
            l_objRow = m_objSheet.createRow(m_iRowCount++);

            l_objCell = l_objRow.createCell(0);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(String.valueOf(l_intSrNo++));

            l_objCell = l_objRow.createCell(1);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getEmpname() + " (" + l_objVisitedDoctorsVO.getEmpcode() + ")"); // TBM Name

            l_objCell = l_objRow.createCell(2);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getDr_name());// Doc Name

            l_objCell = l_objRow.createCell(3);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getPotential_score());// Freq potential score

            l_objCell = l_objRow.createCell(4);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getDoctor_potential());// Freq potential score

            l_objCell = l_objRow.createCell(5);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getSpeciality());//CP_GP_SPL

            l_objCell = l_objRow.createCell(6);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getActualpractice());// Actual practise

            l_objCell = l_objRow.createCell(7);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getPreviousmet());// Lastmet

            l_objCell = l_objRow.createCell(8);
            l_objCell.setCellStyle(m_objCellStyle4);
            l_objCell.setCellValue(l_objVisitedDoctorsVO.getLastmet());// Previousmet

        }
        // Write OutPut Stream
        try {
                out = new FileOutputStream(m_objFile);
                outBf = new BufferedOutputStream(out);
                m_objWorkBook.write(outBf);
            } catch (Exception ioe) {
            ioe.printStackTrace();
            System.out.println(" Exception in chunk write");
        } finally {
            if (outBf != null) {
                outBf.flush();
                outBf.close();
                out.close();

                l_objRow=null;
                l_objCell=null;
            }

        }


    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤独患者 2024-11-02 12:39:52

您不需要在开始写入 Excel 之前将完整列表填充到内存中,而是需要修改代码以使得每个对象在从数据库读取时都写入到文件中。看一下这个问题,了解另一种方法。

Instead of populating the complete list in memory before starting to write to excel you need to modify the code to work in such a way that each object is written to a file as it is read from the database. Take a look at this question to get some idea of the other approach.

谎言月老 2024-11-02 12:39:52

好吧,我不确定 POI 是否可以处理增量更新,但如果可以,您可能想将 10000 行的块写入文件。如果没有,您可能必须改用 CSV(因此无需格式化)或增加内存。

问题是,在写入文件完成之前(在生成所有行并将其写入文件之前),您需要使写入文件的对象适合垃圾回收(不再有来自活动线程的引用)。

编辑:

如果您可以将较小的数据块写入文件,您还必须只从数据库加载必要的数据块。因此,一次加载 50000 条记录,然后尝试写入 5 个 10000 条记录是没有意义的,因为这 50000 条记录可能已经消耗了大量内存。

Well, I'm not sure if POI can handle incremental updates but if so you might want to write chunks of say 10000 Rows to the file. If not, you might have to use CSV instead (so no formatting) or increase memory.

The problem is that you need to make objects written to the file elligible for garbage collection (no references from a live thread anymore) before writing the file is finished (before all rows have been generated and written to the file).

Edit:

If can you write smaller chunks of data to the file you'd also have to only load the necessary chunks from the db. So it doesn't make sense to load 50000 records at once and then try and write 5 chunks of 10000, since those 50000 records are likely to consume a lot of memory already.

九歌凝 2024-11-02 12:39:52

正如托马斯指出的那样,太多的对象占用了太多的空间,并且需要一种方法来减少它。我可以想到几种策略:

  • 您是否需要每次在循环中创建一个新工厂,或者您可以重用它吗?
  • 您可以从一个循环开始,将所需的信息放入新的结构中,然后丢弃旧的结构吗?
  • 您能否将处理拆分为线程链,将信息转发到下一步,从而完全避免构建大型内存消耗结构?

As Thomas points out, you have too many objects taking up too much space, and need a way to reduce that. There is a couple of strategies for this I can think of:

  • Do you need to create a new factory each time in the loop, or can you reuse it?
  • Can you start with a loop getting the information you need into a new structure, and then discarding the old one?
  • Can you split the processing into a thread chain, sending information forwards to the next step, avoiding building a large memory consuming structure at all?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文