嵌入式Derby导致内存不足错误

时间:2015-04-13 12:13:25

标签: java out-of-memory derby clob javadb

当使用CLOB插入大数据记录内容(450kb)时,它会导致内存不足错误。插入200次数据内容后会产生此错误。

下面是它的堆栈跟踪。

DBAppender::updateParameters()::Data.Length()::432164
Exception in thread "AppointmentFileListener" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2367)
    at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415)
    at java.lang.StringBuffer.append(StringBuffer.java:237)
    at java.io.StringWriter.write(StringWriter.java:101) 

我尝试了所有可能的解决方案:

  • 确保完成交易后所有结果集语句都已关闭。

  • 使用setString(), setClob(), setASCIIStream()设置CLOB值。

  • 堆大小增加到1GB和2GB。

代码段

public class DBAppender extends AppenderSkeleton
{
    private void initialize() throws ClassNotFoundException, SQLException
    {
        if (!EmbeddedDBManager.databaseExists())
        {
            EmbeddedDBManager.createDatabase();
        }
        openConnection();
        thread = new WriteThread();
        // start the thread 
        thread.start();
        initialized = true;
    }
    class WriteThread extends Thread
    {
        final int MAX_UPDATE_ATTEMPTS = 100; // number of times to attempt connection to db
        private volatile boolean stop = false;
        public void stopProcessing()
        {
            stop = true;
        }       
        @Override
        public void run()
        {
            LoggingEvent event = null;      
            while (!stop)
            {
                try
                {
                    event = buffer.take();
                    if (event != null)
                    {
                        int tries = 0;
                        while (!stop && tries < MAX_UPDATE_ATTEMPTS)
                        {
                            try
                            {
                                if (connection == null || connection.isClosed())
                                {
                                    openConnection();
                                }       
                                updateParameters(event);
                                statement.execute();
                                break;
                            }
                            catch (Exception e)
                            {
                                tries += 1;                         
                                if (tries < MAX_UPDATE_ATTEMPTS)
                                {
                                    Thread.sleep(1000);
                                }
                                else
                                {
                                    errorHandler.error("Failed to write event to database", e, ErrorCode.WRITE_FAILURE);
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    errorHandler.error("Error in appender WriteThread", e, ErrorCode.FLUSH_FAILURE);
                }
            }
        }
    }
    private void updateParameters(LoggingEvent event) throws SQLException
    {
        statement.clearParameters();
        if (table.equalsIgnoreCase("tracemessages"))
        {
            String data = event.getRenderedMessage();
            statement.setTimestamp(1, new Timestamp(event.getTimeStamp()));
            statement.setLong(2, event.getTimeStamp());
            statement.setString(3, Conversions.field(data, "|", 0));
            statement.setString(4, Conversions.field(data, "|", 1));
            String temp = data.substring(data.indexOf("|", data.indexOf("|") + 1) + 1);
            if (temp.length() > 32600)
            {
                statement.setString(5, temp);
                statement.setString(6, temp.substring(0, 32600));
            }
            else
            {
                statement.setString(5, null);
                statement.setString(6, temp);
            }
            temp = null;
            data = null;
        }
    }
    private String getSQL()
    {
        StringBuilder sql = new StringBuilder();    
        sql.append("insert into ").append(table);
        if (table.equalsIgnoreCase("traceevents"))
        {
            sql.append("(datetime, msecs, threadid, messageid, correlationid, eventtype, eventobject, entity, execkey, data, reference) values (?,?,?,?,?,?,?,?,?,?,?)");
        }
        else
        {
            sql.append("(datetime, msecs, reference, execkey, data, datapart) values (?,?,?,?,?,?)");
        }
        return sql.toString();
    }
    public void close()
    {
        thread.stopProcessing();
        thread.interrupt();
        closeConnection();
        EmbeddedDBManager.removeShutdownListener(this);
        this.closed = true;
    }
    protected void openConnection() throws ClassNotFoundException, SQLException
    {
        connection = EmbeddedDBManager.getConnection(EmbeddedDBManager.DEFAULT_DATABASENAME);
        statement = connection.prepareStatement(getSQL());
    }   
} 

对此有任何建议真的很感激。

0 个答案:

没有答案