title: Java Threads: Memory Leak
body: <p>I implemented simple server-client chat in Java. Here the source for the server:</p>
  
  <pre><code>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();
      }
  }
  </code></pre>
  
  <p>It works fine but there is a problem. For every established connection the memory continuously grows. I presume the problem is that the memory allocated for the threads is not released afterwards but I'm not quite sure. How can I fix that?</p>
  
  <p>EDIT: The client program:</p>
  
  <pre><code>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);
          }
      }
  }
  </code></pre>