Java 在tomcat上使用web套接字泄漏内存
我们正在Windows服务器上使用Tomcat 8.5,并且由于使用web套接字而导致内存泄漏。服务器web套接字如下所示:Java 在tomcat上使用web套接字泄漏内存,java,tomcat,memory,websocket,tomcat8,Java,Tomcat,Memory,Websocket,Tomcat8,我们正在Windows服务器上使用Tomcat 8.5,并且由于使用web套接字而导致内存泄漏。服务器web套接字如下所示: package ad.ecs.async.websocket; import java.io.IOException; import java.util.Arrays; import javax.websocket.CloseReason; import javax.websocket.OnClose; import javax.websocket.OnError;
package ad.ecs.async.websocket;
import java.io.IOException;
import java.util.Arrays;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import ad.common.Global;
import ad.ecs.async.AsyncEngine;
import ad.ecs.async.AsyncResponse;
import ad.ecs.async.AsyncType;
import ad.ecs.db.DatabaseEngine;
import ad.ecs.db.paradox.User;
import ad.ecs.security.engine.SecurityEngine;
/**
* @author Serge Perepel
* @since Aug 23, 2017 12:23:32 PM
*/
@ServerEndpoint(value = "/asyncMsg", encoders = AsyncResponseEncoder.class)
public class ECSAsync {
@OnOpen
public void open(Session session) throws IOException{
session.getBasicRemote().sendText("Connection Established");
}
@OnMessage
public String login(String sessionID, Session session) {
AsyncEngine.INSTANCE.wsConnect(session, sessionID);
org.hibernate.Session dbSession = DatabaseEngine.getSessionFactory().openSession();
try {
int userID = SecurityEngine.INSTANCE.getUserIDBasedOnSessionID(sessionID);
User user = (User) dbSession.get(User.class, userID);
if (user != null) {
if (user.getNextLogin() == 1) {
AsyncResponse response = new AsyncResponse();
response.setType(AsyncType.None);
response.setData(Arrays.asList("PASSWORD"));
response.setObjData("PASSWORD");
AsyncEngine.INSTANCE.addTransientResult(sessionID, response);
}
}
} finally {
dbSession.close();
}
return "ok";
}
@OnClose
public void close(Session session, CloseReason reason) {
AsyncEngine.INSTANCE.wsDisconnect(session);
}
@OnError
public void error(Session session, Throwable error) {
Global.INSTANCE.getLogHelper().exception(error);
//session.close(new CloseReason(closeCode, reasonPhrase));
}
}
前端打开连接并发送无效的sessionID,导致
行AsyncEngine.INSTANCE.wsConnect(session,sessionID)
引发异常,然后在前端发生断开连接。此时,前端打开新的连接,进程进入循环。我假设连接处理程序在发生断开连接后被释放。但它似乎在积累
以下是Eclipse中内存分析器插件的报告:
One instance of "org.apache.coyote.AbstractProtocol$ConnectionHandler"
loaded by "java.net.URLClassLoader @ 0x720029098" occupies 2,153,196,128
(88.10%) bytes. The memory is accumulated in one instance of
"java.util.concurrent.ConcurrentHashMap$Node[]" loaded by "<system class loader>".
Keywords
org.apache.coyote.AbstractProtocol$ConnectionHandler
java.util.concurrent.ConcurrentHashMap$Node[]
java.net.URLClassLoader @ 0x720029098
看起来像
AsyncEngine.INSTANCE.wsConnect
是您的代码。如果您也能为它显示代码,这会有所帮助。正如我在本例中所说,这总是引发异常,但这并不意味着问题不在wsConnect
中。因为它可以打开连接,所以抛出异常而从不关闭它。wsConnect
对websockets没有任何作用,它只是在sessionID匹配的情况下将会话存储到映射中。如果sessionID无效,则抛出异常。我们记录了异常,在日志中看到了数千个异常
public synchronized void wsConnect(Session session, String sessionID) {
SecurityEngine.INSTANCE.checkSession(sessionID); // Exception is thrown here
connections.put(sessionID, session);
if (transientResponses.containsKey(sessionID)) {
transientResponses.get(sessionID).values().stream()
.forEach(p -> addTransientResult(sessionID, p));
}
}