I have this damnable structure:
public void run() {
try {
if (!portField.getText().equals("")) {
String p = portField.getText();
CharSequence numbers = "0123456789";
btnRun.setEnabled(false);
if (p.contains(numbers)) {
ServerSocket listener = new ServerSocket(Integer.parseInt(p));
while (true) {
Socket socket = listener.accept();
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println("Hi there, human.");
} finally {
socket.close();
}
}} else {
JOptionPane.showMessageDialog(null, "Only numbers are allowed.");
}
}
} catch (NumberFormatException | HeadlessException | IOException e) {
e.printStackTrace();
}
}
As you can see, I need to close the listener exactly as I did with the socket. The problem is that if I try to do so after the loop the code will be "unreachable", and if I try to declare a field anywhere for the ServerSocket, I get a NullPointerException. I don't want to close the ServerSocket together with the socket/client because I want to make new connections.
So that's my question:
It's REALLY necessary to close the ServerSocket in this case? The ServerSocket closes itself by its own when the software is shut down? (System.exit(0)). If the ServerSocket continues to run when I close the software just because I have not closed it, then I have a problem, because I can't reach that bloody piece of code to close it :).
Yes. While destroying references to the socket may cause the garbage collector to finalize it, that does not specify that it will be closed. This is implementation-specific in many cases, and can sometimes derail relative to design due to performance or even minute bugs that are hard to track.
Keeping a reference anywhere is a sure bet that it won't be, even with WeakReferences.
Now the OS has a limited(due to its design) number of sockets it can give. As you open more and more sockets, the OS comes under pressure and eventually runs out of sockets, causing the failure of either Java or another program. In addition, depeding on socket options you or defaults may set, this socket may send keepalives, exhausting resources on the other endpoint as well.
On exit, it is closed by the socket registering a shutdown action in its constructor to close it, and/or the OS's automatic cleanup.
You should never rely on OS/JVM behavior or finalization to close your sockets, especially if you have multiple sockets, even if you don't plan to use all of them at the same time.