4

Red Hat で実行するとメモリ リークの問題が発生する Java WebObjects アプリケーションがありますが、Mac OS X で実行するとそのような問題は発生しませんでした。JVM も同様です。

Apple の Java 1.6.0_22 64 ビットを使用する Mac OS X 10.6.5 Sun の Java 1.6.0_20 64 ビットを使用する Red Hat EL 5.0

メモリが不足したときにヒープ ダンプを実行するように構成しました。これを Eclipse メモリ アナライザー ツールで分析すると、HTTP 要求を Web サービスに送信するスレッドを作成するコードの一部に問題があることが示唆されます。スレッドを作成する理由は、Web サービスが使用できない場合があるため、要求にタイムアウトを実装するためです。

誰にもアイデアはありますか?

    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.
4

3 に答える 3

1

WOHTTPConnectionハンドルを閉じる必要がありますか?(私はそのAPIに精通していません...)。

ファローアップ

チェックインすると、connection.readResponse()が接続を閉じるように見えるので、手動で行う必要はありません。

@Rudiger-への呼び出しはconnection.readResponse() 常に成功すると想定しています。問題が、報告されていない例外をスローしている場合はどうなりますか。(デフォルトの動作では、子スレッドでスローされたエラーをサイレントに無視します。)

念のため、finallyブロックで接続ハンドルを閉じる必要があると思います。

WOHTTPConnectionまたはさらに良いことに、完全に捨てる。

于 2010-12-01T03:57:07.587 に答える
1

WOHTTPConnection が壊れているため、使用すべきではないと聞いています。WOHTTPConnection は、接続を閉じる信頼できる方法を提供しません。また、他の点でも信頼できません。

解決策は、Apache HttpComponents HttpClient を使用してコードを書き直すことです

于 2010-12-02T01:45:12.633 に答える
1

問題は、 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();
    }

}

于 2010-12-01T15:26:39.047 に答える