我有一个java webobjects应用程序,它在Red Hat上运行时显示内存泄漏问题,但是当它在Mac OS X上运行时我们没有这样的问题.JVM类似。
Mac OS X 10.6.5使用Apple的64位_ 64位 Red Hat EL 5.0使用Java 1.6.0_20 64位来自Sun
我将它配置为在内存不足时执行堆转储,并使用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.
答案 0 :(得分:1)
您需要关闭WOHTTPConnection
句柄吗? (我不熟悉那个API ......)。
<强>后续强>
签入后,看起来像connection.readResponse()关闭了连接,所以我不需要手动完成。
@Rudiger - 您假设对connection.readResponse()
的呼叫始终成功。如果问题在于它抛出了未报告的异常,该怎么办? (默认行为是静默忽略子线程上抛出的错误。)
我认为你应该关闭finally块中的连接句柄......以防万一。
或者更好的是,完全抛弃WOHTTPConnection
。
答案 1 :(得分:1)
我认为问题是Thread.interrupt实际上并没有停止你的Thread。如果线程正在运行,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();
}
}
答案 2 :(得分:1)