在 Red Hat 上运行时 Java 内存泄漏,但在 Mac OS X 上没有内存泄漏
我有一个 java webobjects 应用程序,在 Red Hat 上运行时显示内存泄漏问题,但在 Mac OS X 上运行时没有出现此类问题。JVM 是相似的。
Mac OS X 10.6.5 使用 Apple 的 java 1.6.0_22 64 位 Red Hat EL 5.0 使用 Sun 的 java 1.6.0_20 64 位
我将其配置为在内存不足时执行堆转储,并使用 eclipse 内存分析器工具对此进行分析表明问题出在创建的代码的一部分中向 Web 服务发送 HTTP 请求的线程。创建线程的原因是为了对请求实现超时,因为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.
I have a java webobjects app which is showing memory leak problems when running on Red Hat but we had no such problems when it was running on Mac OS X. The JVMs are similar.
Mac OS X 10.6.5 using java 1.6.0_22 64 bit from Apple
Red Hat EL 5.0 using java 1.6.0_20 64 bit from Sun
I configured it to do a heap dump when it ran out of memory, and analysing this with the eclipse memory analyzer tool suggests that the problem is in a part of the code which creates a thread which sends an HTTP Request to a web service. The reason for creating the thread is to implement a timeout on the request because the web service is sometimes not available.
Does anyone have any ideas?
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;
}
}
EDIT: leaked class names as reported by eclipse memory analyzer tool:
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我听说 WOHTTPConnection 已损坏,不应使用。 WOHTTPConnection 没有为您提供关闭连接的可靠方法。在其他方面它也是不可靠的。
解决方案是使用 Apache HttpComponents HttpClient 重写代码
I have heard that WOHTTPConnection is broken and shouldn't be used. WOHTTPConnection does not give you a reliable way of closing the connection. It is also unreliable in other ways.
The solution is to rewrite the code using Apache HttpComponents HttpClient
我认为问题在于 Thread.interrupt 实际上并没有停止你的线程。如果线程正在运行,JVM 永远不会清理该线程。
我会向您的线程添加一个 closeConnection 方法,并尝试调用该方法来代替您的 Thread.interrupt 调用或除了您的 Thread.interrupt 调用之外调用该方法。您可能需要对其进行一些修改,但想法是显式停止保持线程运行的 IO:
...
}
I think the problem is that Thread.interrupt does not actually stop your Thread. And the JVM will never clean up the thread if its running.
I would add a closeConnection method to your thread and try calling that instead of or in addition to your Thread.interrupt call. You might need to modify it a bit, but the idea is to explicitly stop the IO that is keeping the Thread running:
...
}
您需要关闭
WOHTTPConnection
句柄吗? (我不熟悉那个 API ...)。跟进
@Rudiger - 您假设对
connection.readResponse()
的调用总是成功。如果问题是抛出未报告的异常怎么办? (默认行为是默默地忽略子线程上引发的错误。)我认为您应该在finally块中关闭连接句柄......以防万一。
或者更好的是,完全放弃
WOHTTPConnection
。Do you need to close the
WOHTTPConnection
handle? (I'm not familiar with that API ...).FOLLOWUP
@Rudiger - you are assuming that the call to
connection.readResponse()
always succeeds. What if the problem is that it is throwing an exception that is not getting reported. (The default behavior is to silently ignore errors thrown on child threads.)I think you should close the connection handle in a finally block ... just in case.
Or better still, ditch
WOHTTPConnection
entirely.