Cause of buffer-free socket error?

I am writing a network program in Java. I use ServerSocket and Socket objects to send and receive messages using TCP. My program works fine if it runs for a short time, but if I run it for a longer time, I get the following error:

java.net.SocketException: No buffer space available (maximum connections reached?): connect at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.PlainSocketImpl.doConnect(Unknown Source) at java.net.PlainSocketImpl.connectToAddress(Unknown Source) at java.net.PlainSocketImpl.connect(Unknown Source) at java.net.SocksSocketImpl.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.<init>(Unknown Source) at java.net.Socket.<init>(Unknown Source) 

I thought it could be because I did not close all the sockets, but I changed my code: I have one class that I create when I want a new socket, and added the finalize method to close it. I also have a finalization method for closing ServerSocket, so I don't know what the problem is.

Also, after receiving the error, if I run the program again, it ran into the problem faster than before. Then, if I wait a while and run it, it will return to the original time.

I really cannot solve this problem, and I have been trying to understand it for ages. Does anyone know what the problem is?

Thanks in advance!

UPDATE:

So, I found out where the error comes from, and this is really strange. I have the following code causing the problem:

 try { sock = new Socket(InetAddress.getByName(ipaddr), port); sock.close(); // os = sock.getOutputStream(); // byte[] arr = s.getBytes(); // os.write(arr); // os.close(); } catch (Exception e) { e.printStackTrace(); } finally { try { sock.close(); } catch (Exception e) { e.printStackTrace(); } } 

As you can see, the code should open the socket and write it. However, even when all the functional code is commented out, as indicated above, so that the socket just opens and then closes immediately, I still get a "no buffer space" error.

I really cannot understand why this is so. The program has multithreading, and each thread periodically creates objects with the above method and calls it. When the lines created and closing the socket are deleted, I no longer get the error, but when they are there, although the socket opens and then closes immediately, I get an error.

Does anyone know why this is happening?

Thank you very much.

0
source share
2 answers

I have one class that I create when I want a new socket, and added a finalize method to close it. I also have a finalize method for closing a ServerSocket, so I don't know what the problem is.

Bzzt. Stop. Check it out. Finalizers are not deterministic at startup (except for some time after the object is no longer available, although it is possible even if the Java application terminates!) - see Destruction and termination . Make sure you use an explicit contract, such as Closable , and call it through to the end (do not wait for the GC to appear).

This problem is most indicative of the "leakage" of external resources - since the GC mainly cares about the pressure of memory and memory, if there is little pressure and / or the GC is not aggressive, it is very easy to run out of the external primarily because the finalizers are not running (yet) . In general, a finalizer is a security network (which does not always work), but does not replace other forms of external resource management.

From the above link:

Java makes no guarantees as to when the garbage collection will occur or in what order the objects will be collected. Therefore, Java cannot guarantee that when (or even will) the finalizer will be called, in what order the finalizers will be called, or which thread the finalizers will execute.

Happy coding.

Edit: See this related question: Why would you ever implement finalize ()? . I like the second answer from Steve Jessop.

+4
source

Do not use finalize to close resources. This will not work reliably.

(The likelihood that resource objects will not be completed soon enough and you will run out of resources. You have no control over when the finalizers will be launched, and it is possible that they will never be launched.)

What you should do is something like this:

  Resource resource = // allocate resource try { // Use the resource ... } catch (SomeException ...) { // Deal with errors from using the resource } finally { try { resource.close()} } catch (SomeException ...) { // Deal with errors from closing the resource } } 
+2
source

All Articles