Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程:内存泄漏_Java_Multithreading_Sockets - Fatal编程技术网

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

我用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 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;