博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

java.io.IOException: Too many open files

Posted on 2011-03-10 15:03  袁立  阅读(1989)  评论(0编辑  收藏  举报

 

1.发生环境

操作系统:redhat linux

运行环境:jdk1.5

 

2.异常详细

 

java.io.IOException: java.io.IOException: Too many open files

        at java.lang.UNIXProcess.<init>(UNIXProcess.java:148)

        at java.lang.ProcessImpl.start(ProcessImpl.java:65)

        at java.lang.ProcessBuilder.start(ProcessBuilder.java:451)

        at java.lang.Runtime.exec(Runtime.java:591)

        at java.lang.Runtime.exec(Runtime.java:464)

        at com.ncs.dnsanalysis.script.ExecuteShellScript.execute(ExecuteShellScript.java:39)

        at com.ncs.dnsanalysis.service.AnalysisHandler.run(AnalysisHandler.java:48)

        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:417)

        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269)

        at java.util.concurrent.FutureTask.run(FutureTask.java:123)

        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)

        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)

        at java.lang.Thread.run(Thread.java:595)

 

 

3.异常发生的位置

Process pro = Runtime.getRuntime().exec(cmds);

 

4.异常分析

在多线程环境中反复调用Runtime.getRuntime().exec(cmds),并将执行命令返回的结果重定向到一个临时文件中,直到任务全部完成,我们知道,每调用Runtime.getRuntime().exec(cmds)一次将在后台开启一个子进程。执行如下命令查看该程序的进程ID

 

[root@localhost DNSAnalysis]# ps -ef | grep java

root     21240     1 98 14:32 ?        00:08:25 java -cp .:./config:./lib/dom4j-1.4.jar:./lib/log4j-1.2.14.jar com.ncs.dnsanalysis.AnalysisServer

root     26636  7783  0 14:40 pts/1    00:00:00 grep java

从结果可以看出进程ID为:21240

 

执行如下命令[[root@localhost root]# lsof -p 21240],查看该进程打开的文件句柄,结果如下:

...............略

 

java    21240 root  mem    REG    8,2 39713589  816507 /opt/jdk150_04/jre/lib/rt.jar

java    21240 root    0r   CHR    1,3            66835 /dev/null

java    21240 root    1u   CHR  136,3                5 /dev/pts/3 (deleted)

java    21240 root    2u   CHR  136,3                5 /dev/pts/3 (deleted)

java    21240 root    3r   CHR    1,8            67263 /dev/random

java    21240 root    4r   CHR    1,9            72528 /dev/urandom

java    21240 root    5w   REG    8,2    14431  473993 /opt/DNSAnalysis/log/log.txt

java    21240 root    7w  FIFO    0,5           302027 pipe

java    21240 root    8r  FIFO    0,5           302028 pipe

java    21240 root    9w  FIFO    0,5           302076 pipe

java    21240 root   10r  FIFO    0,5           302029 pipe

java    21240 root   11r  FIFO    0,5           302077 pipe

java    21240 root   12w  FIFO    0,5           302054 pipe

java    21240 root   14r  FIFO    0,5           302055 pipe

java    21240 root   15r  FIFO    0,5           302078 pipe

java    21240 root   16r  FIFO    0,5           302056 pipe

java    21240 root  678w  FIFO    0,5           301877 pipe

java    21240 root  680r  FIFO    0,5           301878 pipe

java    21240 root  682r  FIFO    0,5           301879 pipe

java    21240 root  690w  FIFO    0,5           301988 pipe

...............略
从结果可以发现名为pipe的文件句柄很多,这是因为执行命令后使用重定向所致。但是过一段时间之后,会慢慢的释放文件句柄。当文件句柄达到一定限制之后,就会引发上面的异常,甚至导致程序崩溃,更严重的整个操作系统都将崩溃,需要重新启动设备。
5.解决方案
既然是文件句柄受限,那么我们可以对上限进行设置;

查看系统允许打开的最大文件数

#cat /proc/sys/fs/file-max

 

查看每个用户允许打开的最大文件数

ulimit -a

发现系统默认的是open files (-n) 1024,问题就出现在这里。

在系统文件/etc/security/limits.conf中修改这个数量限制,

在文件中加入内容:

* soft nofile 65536 
* hard nofile 65536


另外方法:
1.使用ps -ef |grep java   (java代表你程序,查看你程序进程) 查看你的进程ID,记录ID号,假设进程ID为12
2.使用:lsof -p 12 | wc -l    查看当前进程id为12的 文件操作状况
    执行该命令出现文件使用情况为 1052
3.使用命令:ulimit -a   查看每个用户允许打开的最大文件数
    发现系统默认的是open files (-n) 1024,问题就出现在这里。
4.然后执行:ulimit -n 4096

     将open files (-n) 1024 设置成open files (-n) 4096

 

这样就增大了用户允许打开的最大文件数