简单的java循环写入数据库会导致内存不足异常

时间:2014-02-28 22:15:59

标签: java loops java-ee memory-leaks daemon

我有一个循环运行的守护进程:

public class MyDaemon implements Daemon {

    private Thread myThread;
    private boolean stopped = false;

    private DatagramChannel channel;

    @Override
    public void init(DaemonContext daemonContext) throws DaemonInitException,
            Exception {

        myThread = new Thread() {

            @Override
            public synchronized void start() {
                MyDaemon.this.stopped = false;
                super.start();
            }

            @Override
            public void run() {
                            ByteBuffer buf = ByteBuffer.allocate(100);

                while (!stopped) {

                    try {
                        channel.receive(buf);
                        String payload = buf;
                        ArrayList<Element> elements = buf.elements();

                        Message message = new Message();
                        message.setPayload();
                        message.setElements(elements);

                        DataManager controller = null;
                        try {
                            dm = new DataManager();
                        } catch (ClassNotFoundException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (SQLException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        dm.saveMessage(message);
                        Thread.sleep(100);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
            }
        };
    }

    public static void main(String args[]) {

    }

    @Override
    public void start() throws Exception {

        channel = DatagramChannel.open();
        channel.socket().bind(new InetSocketAddress(1400));
        channel.configureBlocking(false);
        myThread.start();
    }

    @Override
    public void stop() throws Exception {

        stopped = true;
        try {
            myThread.join(1000);
        } catch (InterruptedException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }

    @Override
    public void destroy() {
        myThread = null;
    }
}

我的数据管理器类看起来如下所示:

public class DataManager {

    private static String insert = "insert into mytable "
                        + “(payload, elementId, time)”
                        + "values (?,?,?);”;

    public Connection instantiateConnection() throws ClassNotFoundException,
            SQLException {



        Connection connection = DriverManager.getConnection("jdbc connection info”);

        return connection;
    }



    public void saveMessage(Message message) {
        try {
            Connection connection = this.instantiateConnection();

                connection.setAutoCommit(false);
                PreparedStatement ps = connection.prepareStatement(insert);

                for (Element element : message.getElements()) {
                    Timestamp time = new Timestamp(date.getTime());
                    ps.setString(1, message.getPayload());
                    ps.setString(2, element.getId());
                           ps.setTimestamp(3, time);
                    ps.addBatch();
                }
                ps.executeBatch();
                connection.commit();
                ps.close();
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

}

最后,这是运行我的守护程序的ssh文件:

#!/bin/sh

# Setup variables EXEC=/usr/bin/jsvc



PID=/tmp/mydaemon.pid JAVA_HOME=/usr/lib/jvm/jre CLASS_PATH="/home/ec2-user/commons-daemon-1.0.15.jar”:”/MyDaemon.jar" CLASS=MyDaemon USER=ec2-user LOG_OUT=/tmp/mydaemon.out LOG_ERR=/mydaemon.err

do_exec() {
    $EXEC -home "$JAVA_HOME" -cp $CLASS_PATH -user $USER -outfile $LOG_OUT -errfile $LOG_ERR -pidfile $PID $1 $CLASS }

case "$1" in
    start)
        do_exec
            ;;
    stop)
        do_exec "-stop"
            ;;
    restart)
        if [ -f "$PID" ]; then
            do_exec "-stop"
            do_exec
        else
            echo "service not running, will do nothing"
            exit 1
        fi
            ;;
    *)
            echo "usage: daemon {start|stop|restart}" >&2
            exit 3
            ;; esac

这是一套完整的代码。请帮忙!

当它运行时,内存会慢慢增长,直到出现内存不足的异常。

有谁知道什么是泄漏?

2 个答案:

答案 0 :(得分:2)

您正在while循环的每次迭代中分配缓冲区。这是多余的,你不需要它,因为你在循环结束时清除缓冲区。这样做:

  ByteBuffer buf = ByteBuffer.allocate(100); 
  while(!stopped)
  {
     // do something

      buf.clear();
 }

答案 1 :(得分:0)

@Rembo万分感谢!你是对的。

我添加了c3p0连接池,从那时起我就像垃圾收集一样。