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

多线程Java web服务器中的内存泄漏,java,multithreading,sockets,memory-leaks,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(Stri

我有一个多线程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();
            }
        }
    }
}

while(true)
循环中创建线程从来都不是一个好主意。

默认情况下,创建的每个线程都将分配;64位jvm为1mb,其堆栈为32位jvm为128KB(这是针对linux操作系统的,其他详细信息)。尝试
ExecutorService
进行此类操作。线程是有价值的资源。

为每个传入连接启动一个新线程效率极低,可能是内存泄漏的原因

正确的方法是使用具有固定数量可重用线程的线程池

还值得指出的是,线程消耗大量的本机内存(脱离Java堆)和很少的堆内存,因此不会触发垃圾收集,垃圾收集将调用终结器释放本机端

编辑:
另外,代码并没有做你认为它做的事情。将accept置于循环之外意味着代码只会一次又一次地为同一连接启动线程,而不是为每个连接启动一个新线程。

虽然为每个传入连接启动线程效率极低,但这不是内存泄漏。我必须检查-我刚刚创建并启动了一百万个线程,但使用大小有限的集合只保存了100个线程的引用,并且没有任何内存不足的问题。(笔记本电脑确实很快就热起来了)已完成的线程由垃圾收集器清理,不会自行泄漏内存。只有在其他东西驱动GC时,提供的代码才会分配套接字(来自accept)和新线程,如果没有其他东西在分配对象,那么就不会触发GC,该GC是调用终结器释放线程的本机组件所必需的。如果看不到实际的OOM堆栈跟踪,很难说,但我90%确定这将是本机内存耗尽。我假设您在64位机器上进行了测试。
LimitedLinkedHashMap线程=新的LimitedLinkedHashMap(100);while(true){Thread t=new Thread();threads.put(t,Boolean.true);t.start();}
-在64位计算机上为是,但没有Xmx设置;总内存使用量保持不变,为245Mb。驱动GC的唯一事情是线程分配——没有其他事情会占用内存。谢谢。accept在循环中,创建问题时我弄错了:)使用OutOfMemoryError中的堆栈跟踪更新问题,并提供Java版本的详细信息以及运行在哪个平台上