多线程Java web服务器中的内存泄漏
我有一个多线程Java web服务器,它接受来自客户端的请求 RAM中的每个请求都为此请求分配内存,但在套接字关闭后不会清除内存。只有在重新启动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
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版本的详细信息以及运行在哪个平台上