Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在tomcat上使用web套接字泄漏内存_Java_Tomcat_Memory_Websocket_Tomcat8 - Fatal编程技术网

Java 在tomcat上使用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;

我们正在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;
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));
    }
}