zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Linux异常-java.io.IOException: 打开的文件过多

LinuxJAVA文件异常IO 打开 过多 IOException
2023-09-27 14:24:00 时间

 

  • 异常报错如下

      09-Oct-2019 15:37:51.923 严重 [http-nio2-8080-Acceptor-0] org.apache.tomcat.util.net.Nio2Endpoint$Acceptor.run Socket accept failed
      java.util.concurrent.ExecutionException: java.io.IOException: 打开的文件过多
      at sun.nio.ch.CompletedFuture.get(CompletedFuture.java:69)
      at org.apache.tomcat.util.net.Nio2Endpoint$Acceptor.run(Nio2Endpoint.java:398)
      at java.lang.Thread.run(Thread.java:748)
      Caused by: java.io.IOException: 打开的文件过多
      at sun.nio.ch.UnixAsynchronousServerSocketChannelImpl.accept0(Native Method)
      at sun.nio.ch.UnixAsynchronousServerSocketChannelImpl.accept(UnixAsynchronousServerSocketChannelImpl.java:344)
      at sun.nio.ch.UnixAsynchronousServerSocketChannelImpl.implAccept(UnixAsynchronousServerSocketChannelImpl.java:280)
      at sun.nio.ch.AsynchronousServerSocketChannelImpl.accept(AsynchronousServerSocketChannelImpl.java:124)
      ... 2 more
    
      09-Oct-2019 15:37:52.324 严重 [http-nio2-8080-Acceptor-0] org.apache.tomcat.util.net.Nio2Endpoint$Acceptor.run Socket accept failed
      java.util.concurrent.ExecutionException: java.io.IOException: 打开的文件过多
      at sun.nio.ch.CompletedFuture.get(CompletedFuture.java:69)
      at org.apache.tomcat.util.net.Nio2Endpoint$Acceptor.run(Nio2Endpoint.java:398)
      at java.lang.Thread.run(Thread.java:748)
      Caused by: java.io.IOException: 打开的文件过多
      at sun.nio.ch.UnixAsynchronousServerSocketChannelImpl.accept0(Native Method)
      at sun.nio.ch.UnixAsynchronousServerSocketChannelImpl.accept(UnixAsynchronousServerSocketChannelImpl.java:344)
      at sun.nio.ch.UnixAsynchronousServerSocketChannelImpl.implAccept(UnixAsynchronousServerSocketChannelImpl.java:280)
      at sun.nio.ch.AsynchronousServerSocketChannelImpl.accept(AsynchronousServerSocketChannelImpl.java:124)
      ... 2 more
    
      09-Oct-2019 15:37:53.124 严重 [http-nio2-8080-Acceptor-0] org.apache.tomcat.util.net.Nio2Endpoint$Acceptor.run Socket accept failed
      java.util.concurrent.ExecutionException: java.io.IOException: 打开的文件过多
      at sun.nio.ch.CompletedFuture.get(CompletedFuture.java:69)
      at org.apache.tomcat.util.net.Nio2Endpoint$Acceptor.run(Nio2Endpoint.java:398)
      at java.lang.Thread.run(Thread.java:748)
      Caused by: java.io.IOException: 打开的文件过多
      at sun.nio.ch.UnixAsynchronousServerSocketChannelImpl.accept0(Native Method)
      at sun.nio.ch.UnixAsynchronousServerSocketChannelImpl.accept(UnixAsynchronousServerSocketChannelImpl.java:344)
      at sun.nio.ch.UnixAsynchronousServerSocketChannelImpl.implAccept(UnixAsynchronousServerSocketChannelImpl.java:280)
      at sun.nio.ch.AsynchronousServerSocketChannelImpl.accept(AsynchronousServerSocketChannelImpl.java:124)
      ... 2 more

 

______________________________________________________________________________________________

访问服务器时出现java.IOException:打开的文件过多

https://blog.csdn.net/Anthony_1223/article/details/80541463

 

应用部署在一台测试机器上(Linux),最近发现服务好像挂了。上去看了下打出来的日志,发现报错信息一个是java.net.SocketException,一个是Java.IOException,提示打开的文件过多。
后来去查了查:说是第一个是在错误影响到基础的TCP协议时会抛出,第二个则是在错误影响到I/O操作时抛出。
原因:操作系统中打开文件的最大句柄数受限所致,常常发生在多个用户并发访问服务器时,因为为了执行每一个用户的请求,服务器都要加载很多文件(new一个socket就需要一个文件句柄),这就会导致打开文件的句柄缺乏。
解决方法:
1)尽量将类打成jar包,因为一个jar包只消耗一个文件句柄,如果不打包,一个类就消耗一个文件句柄;Java的GC不能关闭网络连接打开的文件句柄,因此如果没有执行close操作,则文件句柄将一直存在,而不能 被关闭,因此也可以设置socket的最大打开数去控制。
2)对操作系统做相关的设置,增加最大文件句柄数量。
下面是第二种方法的步骤:
步骤:
1)linux下输入ulimit -a命令,可查看允许打开的最大文件数等各种信息。如图所示:

 

 

 

open files这一栏默认的是1024(我的截图是修改过后的,所以变成了65536),我们需要做的就是修改这个数量。
2)修改这个配置文件,命令:vi /etc/security/limits.conf
3)在文件中添加以下内容:
* soft nofile 65536
* hard nofile 65536
4)重启服务。 

____________________________________________________________________________________________________________________________________________

 

优化 - linux ulimit 之 fs.file-max

https://blog.csdn.net/wo18237095579/article/details/110007882

max-file:表示系统级别的能够打开的文件句柄①的数量。是对整个系统的限制,并不是针对用户的。
ulimit -n:控制进程级别(比如 Nginx 进程、MySQL 进程)能够打开的文件句柄的数量。提供对 shell 及其启动的进程的可用文件句柄的控制。这是进程级别的。
一边情况下,服务器上的 ulimit 都需要我们自己设置,而不能使用系统默认的,否则会出现文件描述符耗尽的问题。文件句柄达到上限之后的常见错误有:Too many open files 或者 Socket/File: Can’t open so many files 等。

查看 max-file:

$ sysctl -a | grep 'fs.file-max'
fs.file-max = 6553560

$ cat /proc/sys/fs/file-max
6553560 


设置的方式有两种,一种是临时生效,重启后恢复默认。另一种永久生效。

file-max 的修改:

$ echo 6553560 > /proc/sys/fs/file-max
$ sysctl -w "fs.file-max=34166"
// 以上 2 种重启机器后会恢复为默认值

$ echo "fs.file-max = 6553560" >> /etc/sysctl.conf
// 立即生效,此方式永久生效
$ sysctl -p  


ulimit open files 修改:

// 这只是在当前终端有效,退出之后,open files 又变为默认值。当然也可以写到 /etc/profile 中,因为每次登录终端时,都会自动执行 /etc/profile
$ ulimit -HSn 65535

// 加入以下配置,重启即可生效
$ vim /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535

// 如果需要设置当前用户 session 立即生效,可以执行:
$ ulimit -n 65535
 
解释说明
1. 文件句柄:在 Linux 环境中,任何事物都是用文件来表示,设备是文件,目录是文件,socket 也是文件。用来表示所处理对象的接口和唯一接口就是文件。应用程序在读/写一个文件时,首先需要打开这个文件,打开的过程其实质就是在进程与文件之间建立起连接,句柄的作用就是唯一标识此连接。此后对文件的读/写时,目标文件就由这个句柄作为代表。最后关闭文件其实就是释放这个句柄的过程,使得进程与文件之间的连接断开。