Got a problem about server-client:
When server is running, if I want to make some change in ServerThread, for example, the string “Welcome!” to “Hello!”, is that possible to execute that without restart the server? For now, when I change “Welcome!” to something else, it still print out “Welcome!” to client. I have to close eclipse and restart server for this new string working. Is there any way to solve that problem? Thx alot!
Server:
import java.net.*;
import java.io.*;
public class ATMServer {
private static int connectionPort = 8989;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(connectionPort);
} catch (IOException e) {
System.err.println("Could not listen on port: " + connectionPort);
System.exit(1);
}
System.out.println("Bank started listening on port: " + connectionPort);
while (listening)
new ATMServerThread(serverSocket.accept()).start();
serverSocket.close();
}
}
ServerThread:
import java.io.*;
import java.net.*;
public class ATMServerThread extends Thread {
private Socket socket = null;
private BufferedReader in;
PrintWriter out;
public ATMServerThread(Socket socket) {
super("ATMServerThread");
this.socket = socket;
}
public void run(){
try {
out = new PrintWriter(socket.getOutputStream(), true);
out.println("Welcome!");
} catch (IOException e){
e.printStackTrace();
}
}
}
Client:
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
private static int connectionPort = 8989;
public static void main(String[] args) throws IOException {
Socket ATMSocket = null;
PrintWriter out = null;
BufferedReader in = null;
String adress = "";
try {
adress = "127.0.0.1";
} catch (ArrayIndexOutOfBoundsException e) {
System.err.println("Missing argument ip-adress");
System.exit(1);
}
try {
ATMSocket = new Socket(adress, connectionPort);
out = new PrintWriter(ATMSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader
(ATMSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Unknown host: " +adress);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't open connection to " + adress);
System.exit(1);
}
System.out.println(in.readLine());
out.close();
in.close();
ATMSocket.close();
}
}
This is possible but not simple.
The string “Welcome!” is part of the class file (it’s a static String constant). When you change it, Eclipse will create a new .class file and write that to disk.
At the same time, you have a running Java program which uses the same .class file. There are two reasons why the change isn’t picked up:
A Java VM doesn’t reload class files by itself. When a class has been loaded once, it doesn’t update when you change the .class file on the disk. You have to tell the classloader to flush the loaded class from memory and load the .class file again.
There is an instance of this class in the running VM. The instance has a reference to a String object. Even when the class is loaded again, this instance (and its references) don’t change. You have to create a new instance.
To fix the first problem, you need to run your application in Debug mode. Eclipse will then try to tell the VM when .class files have changed. Note that some changes can’t be reloaded by some VMs. For example, Sun’s VM can handle new methods, method parameters, fields, imports. You can only change method bodies. Eclipse will tell you when the reload has failed.
To fix the second issue, stop the thread and start a new one. I suggest a special client “restart” message for this which stops all threads and creates a new pool.
In any case, it’s never necessary to stop Eclipse.