Java Themes: Memory Leak

I implemented a simple server-client chat in Java. Here is the source for the server:

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

It works great, but there is a problem. For each established connection, memory is constantly growing. I assume that the problem is that the memory allocated for the threads will not be released afterwards, but I'm not quite sure. How can i fix this?

EDIT: client program:

 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); } } } 
+4
source share
3 answers

Try to do

 private static class Read extends Thread { private static Socket socket; private static String address; 

and

 private static class Write extends Thread { private static Socket socket; 

for non-static.

Also, I don’t know how you check the memory, but remember that Java collected the garbage and you will see an increase in memory usage initially until the garbage collector (GC) collects it and increases until the next start of the GC. Thus, it constantly increases without any fall for a long time, only then there is a memory leak, otherwise you will go well.


I ran the above code as is and worked for about 1-2 hours, and this is about 54 MB of constant memory usage on a Mac using JDK 6. I do not use the JConsole that comes with jdk to view memory usage. I did not find any problems.

Below is a graph, as I mentioned in mine as well, you have a peak and dipping. In the end, when I stopped the client, it is flat. enter image description here

+4
source

Ivan

a few things to work with threading.

Never do this:

  try { read.join(); write.join(); } catch(InterruptedException e) { } 

Always put something in a catch clause and let it be log.error. You have no chance of knowing that this is happening.

Then all threads / closes, etc. must be included in the finally block. Otherwise, you cannot necessarily close everything you need.

You might want to reuse connections. Try this: http://commons.apache.org/pool/

Can you tell us if you reach sysout to close connections? Basically, try to create journal entries every time you open a connection and every time you close it. You probably see what is missing.

+4
source

Try putting your socket.close () inside the finally block to make sure it works.

But I think your code can have big problems with this, since you are not using the connection pool, you are opening new connections unnecessarily.

+2
source

Source: https://habr.com/ru/post/1392512/


All Articles