Java线程:内存泄漏
我用Java实现了简单的服务器客户端聊天。以下是服务器的源代码:Java线程:内存泄漏,java,multithreading,sockets,Java,Multithreading,Sockets,我用Java实现了简单的服务器客户端聊天。以下是服务器的源代码: public class Server { final private static int PORT = 50000; private static class Read extends Thread { private static Socket socket; private static String address; public Read(Socket
public class Server {
final private static int PORT = 50000;
private static class Read extends Thread {
private static Socket socket;
private static String address;
public Read(Socket socket) {
this.socket = socket;
address = socket.getInetAddress().toString().substring(1);
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg;
while (true) {
msg = in.readLine();
if (msg == null) {
in.close();
return;
}
System.out.println(address + ": " + msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static class Write extends Thread {
private static Socket socket;
public Write(Socket socket) {
this.socket = socket;
}
public void run() {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
String msg;
while (true) {
if (socket.isClosed()) {
out.close();
return;
}
if (stdin.ready()) {
msg = stdin.readLine();
out.println(msg);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
ServerSocket serverSocket;
boolean listening = true;
serverSocket = new ServerSocket(PORT);
while (listening) {
Socket socket = serverSocket.accept();
String address = socket.getInetAddress().toString().substring(1);
System.out.println("Connection Established " + address);
Thread read = new Read(socket);
Thread write = new Write(socket);
read.start();
write.start();
try {
read.join();
write.join();
} catch(InterruptedException e) {
}
socket.close();
System.out.println("Connection Closed " + address);
}
serverSocket.close();
}
}
它工作正常,但有一个问题。对于每个已建立的连接,内存都会不断增长。我认为问题在于分配给线程的内存在之后没有释放,但我不太确定。我怎样才能解决这个问题
编辑:客户端程序:
class Client {
final private static int PORT = 50000;
private static class Read extends Thread {
private Socket socket;
private String address;
public Read(Socket socket) {
this.socket = socket;
address = socket.getInetAddress().toString().substring(1);
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg;
while (true) {
msg = in.readLine();
if (msg == null) {
System.out.println("Connection closed " + address);
System.exit(0);
}
System.out.println(address + ": " + msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static class Write extends Thread {
private Socket socket;
public Write(Socket socket) {
this.socket = socket;
}
public void run() {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
Scanner sc = new Scanner(System.in);
String msg;
while (true) {
msg = sc.nextLine();
out.println(msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
PrintWriter out;
BufferedReader in;
Scanner sc = new Scanner(System.in);
while (true) { //for the test only
Socket socket = null;
try {
socket = new Socket("78.90.68.125", PORT);
} catch(java.net.ConnectException e) {
System.out.println("Connection error: host unreachable");
System.exit(1);
}
/*
String address = socket.getInetAddress().toString().substring(1);
System.out.println("Connection established " + address);
Thread read = new Read(socket);
Thread write = new Write(socket);
read.start();
write.start();
try {
read.join();
write.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
finally {
*/
socket.close();
// }
//System.out.println("Connection closed " + address);
}
}
}
尝试将socket.close()放在finally块中,以确保它运行 但是我认为你的代码可能有更大的问题,因为你没有使用连接池,你不必要打开新的连接。Ivan 使用线程时需要做的一些事情 永远不要这样做:
try {
read.join();
write.join();
} catch(InterruptedException e) {
}
始终在catch子句中放入某些内容,并将其设置为log.error。你没有机会知道它的发生
然后,所有流/关闭等必须进入最终块。否则,你永远无法确保关闭所有必要的东西
您可能希望重用连接。试试这个:
你能告诉我们你是否经常联系sysout来关闭连接吗?
基本上,每次打开和关闭连接时都要尝试创建日志语句。也许你看到了你所缺少的东西。试着去做
private static class Read extends Thread {
private static Socket socket;
private static String address;
及
到非静态
另外,我不知道如何检查内存,但请记住Java是垃圾收集的,在垃圾收集器(GC)收集内存之前,您会看到内存使用量的增加,在下次GC运行之前,内存使用量会再次增加。所以它会持续增加,长时间没有任何下降,只有在内存泄漏的情况下,你才可以继续
我按原样运行了上面的代码,运行了大约1-2个小时,在使用JDK 6的Mac机器上,内存使用稳定在54MB左右。我没有使用jdk附带的
JConsole
来查看mem的使用情况。我没有发现任何问题
下面是我在我的ans中提到的图表,也有峰值和下降。最后当我停止客户端时,它是平的。
我使用系统监视器检查内存。程序达到70mb,然后客户端抛出异常:
线程“main”java.net中的异常。noroutHostException:无法分配请求的地址
。将字段更改为非静态无效。您的客户端是什么?发生故障时您有多少个连接?根据您的逻辑,在给定的时间内似乎只进行了一次连接?为了测试服务器,我将客户端修改为while(true){Socket Socket=new Socket(“IP”,PORT);..Socket.close();}
看起来您的内存没有泄漏,但达到了最大端口号限制。我不太确定我是否理解。
private static class Write extends Thread {
private static Socket socket;