【问题标题】:OutOfMemoryError After 100 junit tests using DAO with hsqldb使用带有 hsqldb 的 DAO 进行 100 次 junit 测试后出现 OutOfMemoryError
【发布时间】:2014-01-04 03:30:22
【问题描述】:

我在启动大约 100 个 junit 测试时遇到了 OutOfMemoryError。我怀疑对虚拟数据库的访问是造成此异常的原因。但是我没有找到问题的根源。

org.springframework.beans.factory.BeanCreationException:在文件 [applicationContext.xml] 中定义名称为“sessionFactory”的 bean 创建错误:调用 init 方法失败;嵌套异常是 java.lang.OutOfMemoryError: Java heap space 引起:java.lang.OutOfMemoryError: Java heap space

java.lang.NullPointerException 在 org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:125) 在 myproj.utils.JUnit4DaoTestCase.deleteDataSet(JUnit4DaoTestCase.java:192) 在 myproj.dao.PrestationEptDAOTest.tearDown(PrestationEptDAOTest.java:48) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:592) 在 org.junit.internal.runners.BeforeAndAfterRunner.invokeMethod(BeforeAndAfterRunner.java:74) 在 org.junit.internal.runners.BeforeAndAfterRunner.runAfters(BeforeAndAfterRunner.java:65) 在 org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:37) 在 org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75) 在 org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45) 在 org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:71)

我怀疑这个类是造成内存泄漏的原因。所有junit测试都使用这个遗留类。它在 DatabaseOperation.DELETE.execute(connection, dataSet); 行失败了

public abstract class JUnit4DaoTestCase extends JUnit4TestCase
{
    private SessionFactory sessionFactory;

    private Session session;

    private IDatabaseConnection connection = null;

    protected static final String schemaName;

    public static final String DBUNIT_XML_PATH = "metadata/dbunit/";

    static
    {
        final ResourceBundle db = ResourceBundle.getBundle("database");
        schemaName = db.getString("database.schema");
    }

    public void setUp() throws Exception
    {
        super.setUp();

        // récupération session pour traiter lazy
        this.sessionFactory = (SessionFactory) ctx.getBean("sessionFactory");

        session = SessionFactoryUtils.getSession(this.sessionFactory, true);
        TransactionSynchronizationManager.bindResource(this.sessionFactory, new SessionHolder(
                session));

        if(!isTablesExist(session.connection()) ) {
            createTables(session.connection());
        }
        connection = new DatabaseConnection(session.connection(), schemaName);

    }

    private boolean isTablesExist(Connection conn) {
        Statement stmt = null;
        try {

            stmt = conn.createStatement();
            stmt.execute("SELECT * FROM SCENARIO_DESC");
            return true;

           }catch(SQLException se){
              return false;
           }catch(Exception e){
              return false;
           }finally{
              try{
                 if(stmt!=null)
                    stmt.close();
              }catch(SQLException se){
              }
              try{
                 if(conn!=null)
                    conn.close();
              }catch(SQLException se){
                 se.printStackTrace();
              }
           }

    }

    private void createTables(Connection conn) {
        String fileScriptSql = "";
        Statement stmt = null;
        try {
            fileScriptSql = FileUtil.convertFileToString("target/Orchestra/WEB-INF/test-classes/createTables_hlsql.sql");

            stmt = conn.createStatement();
            stmt.execute(fileScriptSql);
            System.out.println("Created table in given database...");

           }catch(SQLException se){
              se.printStackTrace();
           }catch(Exception e){
              e.printStackTrace();
           }finally{
              try{
                 if(stmt!=null)
                    stmt.close();
              }catch(SQLException se){
              }
              try{
                 if(conn!=null)
                    conn.close();
              }catch(SQLException se){
                 se.printStackTrace();
              }
           }
           System.out.println("All tables created in virtual database Hsql!");
    }

    @After
    public void tearDown() throws Exception
    {
        try {
        TransactionSynchronizationManager.unbindResource(sessionFactory);
        SessionFactoryUtils.releaseSession(session, sessionFactory);
        } finally {
            if(connection!=null) {
                connection.close();
            }
            if(session!=null) {
                session.close();
            }
            if(sessionFactory!= null) {
                sessionFactory.close();
            }

        }
    }

    public final void insertDataSet(final IDataSet dataSet) throws HibernateException, SQLException, DatabaseUnitException, FileNotFoundException, IOException
    {
        //SessionFactory sessionFactory = (SessionFactory) ctx.getBean("sessionFactory");
        //Session session = SessionFactoryUtils.getSession(sessionFactory, true);



        //connection = new DatabaseConnection(session.connection(), schemaName);
        try
        {
            DatabaseOperation.INSERT.execute(connection, dataSet);
        }
        catch (DatabaseUnitException e)
        {
            e.printStackTrace();
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        finally {
            if(session != null) {
                session.close();
            }
        }
    }

    public final void deleteDataSet(final IDataSet dataSet) throws HibernateException, DatabaseUnitException
    {
        //SessionFactory sessionFactory = (SessionFactory) ctx.getBean("sessionFactory");
        //Session session = SessionFactoryUtils.getSession(sessionFactory, true);
        //IDatabaseConnection connection = null;
        //connection = new DatabaseConnection(session.connection(), schemaName);
        try
        {
            **DatabaseOperation.DELETE.execute(connection, dataSet);**
        }
        catch (DatabaseUnitException e)
        {
            e.printStackTrace();
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        finally {
            if(session != null) {
                session.close();
            }
        }
    }

    public final void deleteDataSetByQuery(final String tableName, final String whereCondition,
            final String pkField)
    {
        //IDatabaseConnection connection = null;

        try
        {
            //connection = new DatabaseConnection(session.connection(), schemaName);
            QueryDataSet partialDataSet;
            partialDataSet = new QueryDataSet(connection);
            partialDataSet.addTable(tableName, "select * from " + tableName + " where "
                    + whereCondition);
            if (partialDataSet.getTable(tableName).getRowCount() > 0)
            {
                if (pkField != null && !pkField.equals(""))
                {
                    // indicate primery
                    DefaultColumnFilter colFilter = new DefaultColumnFilter();
                    colFilter.includeColumn(pkField);
                    connection.getConfig().setProperty(
                            "http://www.dbunit.org/properties/primaryKeyFilter", colFilter);
                }
                DatabaseOperation.DELETE.execute(connection, partialDataSet);
            }
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (DatabaseUnitException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /**
     * @param tableName
     *            String
     * @param filter
     *            String
     * @throws DaoException
     *             DaoException
     */
    public final void deleteRecordsFromTable(final String tableName, final String filter)
            throws DaoException
    {
        try
        {
            String whereCondition = "";
            if (filter != null && !filter.equals(""))
            {
                whereCondition = " where " + filter;
            }
            String hql = "delete from " + tableName + whereCondition;
            Query query = session.createSQLQuery(hql);
            query.executeUpdate();
        }
        catch (final DataAccessException e)
        {
            throw new DaoException("errorDAO.removeInstance", e);
        }
    }
    /**
     * @param tabName
     *            String
     * @param filter
     *            String
     * @return BigDecimal count of the table records
     */
    public final BigDecimal getRecordCount(final String tabName, final String filter)
    {
        String whereCondition = "";
        if (filter != null && !filter.equals(""))
        {
            whereCondition = (" where " + filter);
        }
        final Query sqlQuery = session.createSQLQuery("select count(*) from " + tabName
                + whereCondition);

        return (BigDecimal) sqlQuery.uniqueResult();
    }

谢谢

【问题讨论】:

    标签: java junit hsqldb


    【解决方案1】:

    您得到的实际错误是由于测试后存在非常大的数据集引起的。 DatabaseOperation.DELETE.execute(connection, dataSet) 的内部实现可能是使用了DELETE FROM SCENARIO_DESC 之类的SQL 语句,并且表的行数太多,无法放入内存。

    您可以增加内存分配以避免错误。

    还有一个查询会导致内存不足错误。在isTableExist(Connection con) 中有一个错误的查询来确定表是否存在。它返回表中的所有行。只需将其替换为最多返回 0 或 1 行的内容即可:

    SELECT * FROM SCENARIO_DESC LIMIT 1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-10
      • 2011-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-21
      • 2014-09-30
      • 2020-01-17
      相关资源
      最近更新 更多