1

Apache Commons デーモンを実装する次の Java デーモンがあります。これは、icedtea6 を使用して ec2 amazon ami で実行されています。

public class MainDaemon implements Daemon {

private Thread myThread; 
private boolean stopped = false;

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

    String[] args = daemonContext.getArguments(); 

    myThread = new Thread(){

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

        @Override
        public void run() {             
            while(!stopped){

                byte[] rcvMsg = incomingBinaryMessage;

                MessageCreator tmc = new MessageCreator();
                Message message = null;
                try {
                    message = tmc.createMessage(rcvMsg);
                System.out.println(message);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };
}

@Override
public void start() throws Exception {
    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;
}
}

MessageCreator は、バイト配列入力ストリームからデータを読み取り、出力をオブジェクトに配置して返します。

public Message createMessage(byte[] rcvMsg) {

Message message = new Message();
ByteArrayInputStream bais = new ByteArrayInputStream(rcvMsg);
DataInput input = new DataInputStream(bais);

    try {

        int MsgType = 0;
        MsgType = input.readShort();

        message.setType(MsgType);

        return message;

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return null;
}

メッセージは pojo です。

public class Message {

private int type;

public int getType() {
    return type;
}
public void setType(int type) {
    this.type = type;
}
}

デーモンが実行されると、メモリ不足の例外が発生するまで、メモリがゆっくりと増加します。

このメソッドの呼び出しをコメントアウトすると、デーモンが実行するセッション全体でメモリが一定のままになるため、これが messageconstructor クラスで発生していることがわかります。

数時間後に次のエラーが表示されます。

Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOfRange(Arrays.java:3221)
    at java.lang.String.<init>(String.java:233)
    at java.lang.StringBuilder.toString(StringBuilder.java:447)
    at sun.net.www.protocol.jar.Handler.parseContextSpec(Handler.java:138)
    at sun.net.www.protocol.jar.Handler.parseURL(Handler.java:84)
    at java.net.URL.<init>(URL.java:614)
    at java.net.URL.<init>(URL.java:482)
    at sun.misc.URLClassPath$JarLoader.checkResource(URLClassPath.java:688)
    at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:773)
    at sun.misc.URLClassPath.getResource(URLClassPath.java:185)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:209)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:435)
    at com.mysql.jdbc.PreparedStatement.getInstance(PreparedStatement.java:872)
    at com.mysql.jdbc.ConnectionImpl.clientPrepareStatement(ConnectionImpl.java:1490)
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4253)
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4152)
    at MySQLConnect.insertTagEncounters(MySQLConnect.java:89)
    at DataControllerImp.saveMessage(DataControllerImp.java:35)
    at MainDaemon$1.run(MainDaemon.java:74)

メモリリークしている実行ループで MessageConstructor を作成する際に何が間違っていますか?

4

0 に答える 0