多线程Java Web服务器中的内存泄漏

时间:2018-02-04 13:14:43

标签: java multithreading sockets memory-leaks

我有一个多线程Java Web服务器,它接受来自客户端的请求。

RAM中的每个请求都为此请求分配内存,但在套接字关闭后不会清除它。只有在重新启动Web服务器后才会进行清理。

如果是内存泄漏,那么它可以在哪部分代码中出现?

我的代码:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Main {
    public static void main(String[] args) {
        try (ServerSocket server = new ServerSocket(80)) {
            Socket socket = server.accept();
            while (true) {
                new Thread(new Client(socket)).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class Client implements Runnable {
    private Socket socket;

    Client(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            System.out.println("run");
        } finally {
            try {
                socket.close();
                System.out.println("Socket closed: " + socket);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

为每个传入连接启动一个新线程是非常低效的,可能就是泄漏内存。

正确的方法是使用具有固定数量的线程的线程池,这些线程可以重复使用。

还值得指出的是,线程消耗大量本机内存(在Java堆之外)而在堆内存上消耗很少,因此不会触发垃圾收集,而垃圾收集又会调用终结器来释放本地方。

编辑: 代码也没有做你认为它做的事情。在循环之外接受意味着代码只会为agian上的同一连接启动线程,而不是每个连接的新线程。

答案 1 :(得分:0)

while(true)循环中创建线程绝不是一个好主意 默认情况下,创建的每个Thread都将分配; 1mb用于64位jvm,128kb用于32位jvm用于其堆栈(这是针对linux os,其他细节here)。尝试ExecutorService来做这类事情。线程是宝贵的资源。