Fixing Too Many Open Files Exception (I use try-catch-finally)

I have a web service written in JAVA (version 1.8) that connects HSM and sends / receives data through a socket. My application is deployed on Apache Tomcat/8.5.14 on linux .

Although I close the socket connection correctly, I have

java.net.SocketException: too many open files

and here is my class

 public class myClass implements AutoCloseable { Socket socket; DataInputStream in; DataOutputStream out; public myClass(String ip, int port) throws Exception { try { socket = new Socket(ip, port); in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); } catch (IOException e) { throw new Exception("Connecting to HSM failed" + e); } } public String sendCommandToHsm(String command) throws IOException { out.writeUTF(command); out.flush(); return in.readUTF(); } @Override public void close() { if (socket != null && !socket.isClosed()) { try { socket.close(); } catch (IOException e) { lgg.info("Closing of socket failed", e); } } if (in != null) { try { in.close(); } catch (IOException e) { lgg.info("Closing of inputStream failed", e); } } if (out != null) { try { out.close(); } catch (IOException e) { lgg.info("Closing of outputStream failed", e); } } } } 

Here is my class

 try (MyClass myClass = new MyClass(ip, port);) { myClass.sendCommandToHsm("my command"); } 

I increased the maximum number of open files on the server from the default value (1024) to 8192, and the same Exception appeared again several times later.

I'm thinking of creating a Socket Connection Pool , is that a good idea?

Can you offer any other solutions?

+7
java linux exception sockets connection-pooling
source share
1 answer

Although I close the socket connection correctly ...

You seem to be there, but I think there are a couple of problems. (I do not know that this is the reason for your leak, but the first is a plausible explanation.)

Problem 1.

 public myClass(String ip, int port) throws Exception { try { socket = new Socket(ip, port); in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); } catch (IOException e) { throw new Exception("Connecting to HSM failed" + e); } } 

If an exception is thrown when configuring the threads, the socket will leak.

Problem 2

 public void close() { if (socket != null && !socket.isClosed()) { try { socket.close(); } catch (IOException e) { lgg.info("Closing of socket failed", e); } } if (in != null) { try { in.close(); } catch (IOException e) { lgg.info("Closing of inputStream failed", e); } } if (out != null) { try { out.close(); } catch (IOException e) { lgg.info("Closing of outputStream failed", e); } } } 

You are closing the wrong order. Before closing socket you must 1 close in and out . In particular, if out has buffered data, then closing out will try to collapse ... what happens if you already closed socket .

In addition, if socket.close() or in.close() does not work for a different reason than an IOException , subsequent closures will be skipped. Therefore, you should use finally here.

Also, the call to isClosed() is redundant. Calling close() resource that is already closed should not do anything. This is part of the close() contract.

Finally, calling close() on the socket should 2 automatically close the low-level file descriptors under in and out . Therefore, it might be best to do this:

 public void close() { if (socket != null) { try { socket.close(); } catch (IOException e) { lgg.info("Closing of socket failed", e); } } } 

If this does not fix the leaks, I suggest you use netstat and lsof to try to find out if the leaks are open files or open sockets.


I'm thinking of creating a Socket Connection pool, is this a good idea?

Yes ... if you can find an existing (well-designed and tested) library that meets your requirements. Deploying a trusted pool from scratch is not trivial.

But note:

  • An improperly implemented (or used) pool may leak file descriptors.
  • The server side should be able to cope with a number of requests / responses to the same connection.
  • If you have too many simultaneous open connections in different places, then the pool should find a way to close some of them ...

1 - It is debatable whether to close <T23> before in . On the one hand, closing out dumps outstanding data to the server. On the other hand, by the time myClass.close() was called, the server response would not be read. In addition, the sendCommandToHsm method sendCommandToHsm reset ... so there should be no outstanding data.

2 - javadoc for socket.close() says: "Closing this socket will also close the InputStream and OutputStream ."

+1
source share

All Articles