简体   繁体   English

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

[英]Memory leak in a multithreaded Java web server

I have a multithreaded Java web server that accepts requests from clients.我有一个多线程 Java Web 服务器,它接受来自客户端的请求。

Each request in the RAM allocates memory for this request, but it is not cleared after the socket is closed. RAM中的每个请求都会为这个请求分配内存,但是socket关闭后不会被清除。 Cleanup occurs only after the web server is restarted.仅在重新启动 Web 服务器后才会进行清理。

If it is a memory leak, then in which part of the code can it occur?如果是内存泄漏,那么在代码的哪一部分会发生呢?

My code:我的代码:

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();
            }
        }
    }
}

Starting a new thread for every incoming connection is INCREDIBLY inefficient and is probably what is leaking memory.为每个传入连接启动一个新线程的效率非常低,可能是内存泄漏的原因。

The correct approach is to use a thread pool with a fixed number of threads that are reused.正确的方法是使用具有固定数量可重用线程的线程池。

It's also worth pointing out that threads consume large amounts of native memory (off the Java heap) and very little on heap memory, so will not trigger garbage collection which in turn will call the finalizer to free up the native side.还值得指出的是,线程消耗大量本机内存(在 Java 堆之外),而在堆内存上消耗很少,因此不会触发垃圾收集,而垃圾收集又会调用终结器来释放本机端。

EDIT: Also the code doesn't do what you think it does.编辑:此外,代码并没有做你认为的那样。 Having the accept outside the loop means that the code will just spin up threads for the same connection over and over agian, not a new thread for each connection.在循环外接受 accept 意味着代码只会一遍又一遍地为同一连接启动线程,而不是为每个连接启动新线程。

Creating threads in while(true) loop is never a good idea.while(true)循环中创建线程从来都不是一个好主意。
By default, each Thread created will allocate;默认情况下,每个创建的线程都会分配; 1mb for 64 bit jvm and 128 kb for 32 bit jvm for its stack (this is for linux os, other details here ). 1mb 用于 64 位 jvm,128 kb 用于 32 位 jvm 的堆栈(这是针对 linux 操作系统,其他详细信息请点击此处)。 Try ExecutorService for this kind of things.为这种事情尝试ExecutorService Threads are valuable resources.线程是宝贵的资源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM