4

我有一个 java webobjects 应用程序,它在 Red Hat 上运行时显示内存泄漏问题,但在 Mac OS X 上运行时我们没有这样的问题。JVM 是相似的。

Mac OS X 10.6.5 使用来自 Apple Red Hat EL 5.0 的 java 1.6.0_22 64 位,使用来自 Sun 的 java 1.6.0_20 64 位

我将它配置为在内存不足时执行堆转储,并使用 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

我认为问题在于 Thread.interrupt 实际上并没有停止你的线程。如果线程正在运行,JVM 将永远不会清理线程。

我会在你的线程中添加一个 closeConnection 方法,并尝试调用它来代替你的 Thread.interrupt 调用,或者除了你的 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 回答
1

我听说 WOHTTPConnection 坏了,不应该使用。WOHTTPConnection 没有为您提供关闭连接的可靠方法。它在其他方面也是不可靠的。

解决方案是使用 Apache HttpComponents HttpClient 重写代码

于 2010-12-02T01:45:12.633 回答