Утечка памяти Java при работе в Red Hat, но не утечка памяти в Mac OS X - PullRequest
3 голосов
/ 01 декабря 2010

У меня есть приложение java webobjects, которое показывает проблемы утечки памяти при работе в Red Hat, но у нас не было таких проблем, когда оно работало в Mac OS X. JVM похожи.

Mac OS X 10.6.5 с использованием 64-разрядной версии Java 1.6.0_22 от Apple Red Hat EL 5.0 с использованием 64-разрядной версии Java 1.6.0_20 от Sun

Я настроил ее для выполнения дампа кучи, когда онне хватило памяти, и анализ этого с помощью инструмента анализатора памяти eclipse позволяет предположить, что проблема заключается в части кода, которая создает поток, который отправляет HTTP-запрос веб-службе.Причиной создания потока является использование тайм-аута для запроса, поскольку веб-служба иногда недоступна.

У кого-нибудь есть идеи?

    WOHTTPConnection connection = new WOHTTPConnection(host, port);
    WORequest request = new WORequest(strMethod, strQuery, strHttpVersion, nsdHeader, content, null);

    WebServiceRequester theRequester = new WebServiceRequester(connection, request);
    Thread requestThread = new Thread(theRequester);
    requestThread.start();
    try {
            requestThread.join(intTimeoutSend);  //timeout in milliseconds = 10000
            if ( requestThread.isAlive() ) {
                requestThread.interrupt();
            }
    } catch(InterruptedException e) { 

    }
    requestThread = null;
    if(!theRequester.getTfSent()) {
           return null;
    }
    WOResponse response = connection.readResponse();

...

class WebServiceRequester implements Runnable {

    private WORequest theRequest;
    private WOHTTPConnection theConnection;
    private boolean tfSent = false;

    public WebServiceRequester(WOHTTPConnection c, WORequest r) {
        theConnection = c;
        theRequest = r;
    }

    public void run() {
        tfSent = theConnection.sendRequest(theRequest);
    }

    public boolean getTfSent() {
        return tfSent;
    }
}

РЕДАКТИРОВАТЬ: утечка имен классов в соответствии с анализатором памяти Eclipse:

1,296 instances of "java.lang.Thread", loaded by "<system class loader>" occupy 111,947,632 (43.21%) bytes.
1,292 instances of "er.extensions.eof.ERXEC", loaded by "java.net.URLClassLoader @ 0x2aaab375b7c0" occupy 37,478,352 (14.46%) bytes.
1,280 instances of "er.extensions.appserver.ERXRequest", loaded by "java.net.URLClassLoader @ 0x2aaab375b7c0" occupy 27,297,992 (10.54%) bytes.

Ответы [ 3 ]

1 голос
/ 01 декабря 2010

Я думаю, что проблема в том, что Thread.interrupt на самом деле не останавливает ваш поток.И JVM никогда не очистит поток, если он работает.

Я бы добавил метод closeConnection в ваш поток и попытался бы вызвать его вместо или в дополнение к вашему вызову Thread.interrupt.Возможно, вам придется немного его изменить, но идея состоит в том, чтобы явно остановить IO, поддерживающий работу потока:

WOHTTPConnection connection = new WOHTTPConnection(host, port);
WORequest request = new WORequest(strMethod, strQuery, strHttpVersion, nsdHeader, content, null);

WebServiceRequester theRequester = new WebServiceRequester(connection, request);
Thread requestThread = new Thread(theRequester);
requestThread.start();
try {
        requestThread.join(intTimeoutSend);  //timeout in milliseconds = 10000
        if ( requestThread.isAlive() ) {
            requestThread.closeConnection();
            requestThread.interrupt();
        }
} catch(InterruptedException e) { 

}
requestThread = null;
if(!theRequester.getTfSent()) {
       return null;
}
WOResponse response = connection.readResponse();

...

class WebServiceRequester implements Runnable {

    private WORequest theRequest;
    private WOHTTPConnection theConnection;
    private boolean tfSent = false;

    public WebServiceRequester(WOHTTPConnection c, WORequest r) {
        theConnection = c;
        theRequest = r;
    }

    public void run() {
        tfSent = theConnection.sendRequest(theRequest);
    }

    public boolean getTfSent() {
        return tfSent;
    }

    public void closeConnection() {
        this.theConnection.close();
    }

}

1 голос
/ 02 декабря 2010

Я слышал, что WOHTTPConnection не работает и не должен использоваться. WOHTTPConnection не дает вам надежного способа закрытия соединения. Это также ненадежно в других отношениях.

Решение состоит в том, чтобы переписать код с помощью Apache HttpComponents HttpClient

1 голос
/ 01 декабря 2010

Вам нужно закрыть ручку WOHTTPConnection? (Я не знаком с этим API ...).

Followup

Установлено, похоже, что connection.readResponse () закрывает соединение, поэтому мне не нужно делать это вручную.

@ Rudiger - вы предполагаете, что вызов connection.readResponse() всегда завершается успешно. Что делать, если проблема в том, что он вызывает исключение, о котором не сообщается. (Поведение по умолчанию - игнорировать ошибки, возникающие в дочерних потоках.)

Я думаю, вы должны закрыть дескриптор соединения в блоке finally ... на всякий случай.

Или, что еще лучше, ров WOHTTPConnection целиком.

...