I implemented simple server-client chat in Java. Here 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 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?
EDIT: The 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);
}
}
}
Try making
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;
to non-static.
Also, I dont know how you checking for memory, but do remember that Java is garbage collected and you will see increase in memory usage initially till the time garbage collector (GC) collects it and will increase again till next GC run. So it consistently increasing without any dip for long time only then there is a memory leak else you are good to go.
I ran the above code as is and ran for around 1-2 hours and it is steady memory usage of around 54MB on Mac machine using JDK 6. I am not using JConsole
that comes with jdk to see mem usage. I found NO issues.
Below is the graph as I mentioned in my ans also, you have peak and dip ..in the end when I stopped client it is flat.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With