toomanyopenfile:java Too many open files打开的文件过多

问题描述
以下两个堆栈跟踪指示同个问题并报告相同消息:打开文件过多丅

异常 1
java.net.SocketException: Too many open files


at java.net.PlainSocketImpl.accept(Compiled Code)
at java.net.ServerSocket.implAccept(Compiled Code)
at java.net.ServerSocket.accept(Compiled Code)
at weblogic.t3.srvr.ListenThread.run(Compiled Code)

异常 2
java.io.IOException:打开文件过多


at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.(UNIXProcess.java:54)
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.(UNIXProcess.java:54)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Runtime.java:551)
at java.lang.Runtime.exec(Runtime.java:477)
at java.lang.Runtime.exec(Runtime.java:443)
...

个异常在影响到基础 TCP 协议时抛出而第 2个异常则在影响到 I/O 操作时抛出
这两个异常都是由阻止服务器类似问题所产生该问题可通过下面研究思路方法来解决

故障排除
请注意并非下面所有任务都需要完成有些问题仅通过执行几项任务就可以解决

快速链接:
为什么发生此问题?
监视文件描述符
检查打开文件
如何以及何时发布文件描述符?
已知 WebLogic Server 问题
文件描述符和设置



问题描述
以下两个堆栈跟踪指示同个问题并报告相同消息:打开文件过多丅

异常 1
java.net.SocketException: Too many open files


at java.net.PlainSocketImpl.accept(Compiled Code)
at java.net.ServerSocket.implAccept(Compiled Code)
at java.net.ServerSocket.accept(Compiled Code)
at weblogic.t3.srvr.ListenThread.run(Compiled Code)

异常 2
java.io.IOException:打开文件过多


at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.(UNIXProcess.java:54)
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.(UNIXProcess.java:54)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Runtime.java:551)
at java.lang.Runtime.exec(Runtime.java:477)
at java.lang.Runtime.exec(Runtime.java:443)
...

个异常在影响到基础 TCP 协议时抛出而第 2个异常则在影响到 I/O 操作时抛出
这两个异常都是由阻止服务器类似问题所产生该问题可通过下面研究思路方法来解决

故障排除
请注意并非下面所有任务都需要完成有些问题仅通过执行几项任务就可以解决

快速链接:
为什么发生此问题?
监视文件描述符
检查打开文件
如何以及何时发布文件描述符?
已知 WebLogic Server 问题
文件描述符和设置

为什么发生此问题?

这些异常指出操作系统 (OS) 资源问题和操作系统和 JVM 进程用完文件描述符原因(请参阅什么是文件描述符?)

在几个并发用户连接到服务器的后通常会发生此问题Java 打开许多文件以便读取运行应用所必需大量应用会使用许多文件描述符这会导致缺乏新文件描述符同样每个新套接字都需要个描述符客户端和服务器通过 TCP 套接字进行通信在和服务器建立连接时每个浏览器 http 请求都使用 TCP 套接字

定要首先监视文件描述符并了解这些诊断思路方法如何告知您有关打开文件状态和其它潜在问题在针对操作系统逐步执行此故障排除部分的后可能有必要增加文件描述符数量(请参阅文件描述符和设置)

返回页首

监视文件描述符

解决思路方法指导原则
下面是般指导原则和考虑事项:

确定文件描述符总数是否太少或者某些文件描述符是否未被正确释放
这可以通过以下思路方法来诊断:在区别时期检查文件描述符总数确定此数量是有所减少还是直增加
如果此数量有所减少则应当增加文件描述符最大数量以防止该问题再次发生(如何在区别平台上定义文件描述符数量)
此变化可以和减少连接在断开的前保持 TIME_WAIT 状态时间结合起来(如何以及何时发布文件描述符?)在繁忙服务器上缺省值(240 秒)会延迟其它连接企图从而将限制最大连接数量
如果此数量直增加则应当确定某些描述符处理时间是否过长(文件没有正确地关闭 - 如何以及何时发布文件描述符?)以及所创建文件是否过多(例如驱动直为每个新 JDBC 连接加载文件)
加载 jar 文件还可能减少所使用文件描述符数量每个 jar 文件都使用个描述符即使每个单独加载类都将使用个描述符时也是如此
您可以使用下列指导原则来监视和诊断所有描述符如何由个进程使用(这取决于您操作系统):

返回页首

检查打开文件

Unix 平台
在诸多工具中lsof (LiSt Open Files) Unix 管理工具(适用于 Solaris、Tru64、HP-UX、Linux 和 AIX)显示有关打开文件和网络文件描述符信息包括它们类型、大小和 i-节点

对于特定进程其语法如下所示:

lsof -p <进程 pid>
举例 1
以下命令在 Solaris 2.7 启动 WLS 8.1SP1 后立即执行它表明运行服务器 Java 进程 (pid 390) 分配了 84 个文件描述符此数量远小于文件描述符缺省硬极限


$ lsof -p 390 | wc -l
84

在异常出现的后可以执行此命令以确保此 Java 进程达到了打开文件最大数量这将确认该进程缺乏文件描述符

然后您可以运行 $ lsof -p <pid> 并将输出结果重定向到某个文件以检查打开每个文件如果某个应当关闭文件却出现在列表中您可以探查此文件以前没有按照预期方式关闭原因

下面是 lsof 输出结果片断:

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 29733 usera cwd VDIR 176,22 4096 4300274 /home/usera/810/user_projects/mydo
java 29733 usera txt VREG 176,22 36396 6642305 /home/usera/810/jdk141_02/bin/java
java 29733 usera txt VREG 176,22 1251192 10818087 /home/usera/810/user_projects/mydo/myserver/.wlnotdelete/extract/myserver_uddi_uddi/
jarfiles/_wl_cls_gen.jar
java 29733 usera txt VREG 176,22 511935 10074851 /home/usera/810/user_projects/mydo/myserver/.wlnotdelete/extract/myserver_uddi_uddi/
jarfiles/WEB-INF/lib/jsse39153.jar
java 29733 usera txt VREG 176,22 2305960 6000676 /home/usera/810/user_projects/mydo/myserver/.ernal/uddi.war
java 29733 usera txt VREG 176,22 1227013 1385413 /home/usera/810/weblogic81/common/eval/pobase/lib/pbserver44.jar
java 29733 usera txt VREG 176,22 653661 69379 /home/usera/810/weblogic81/server/lib/ant/
optional.jar

lsof .h 显示所有可能语法和选项最新版本可在以下网址中找到:http://ftp.cerias.purdue.edu/pub/tools/unix/sysutils/lsof/

文件描述符将用于每个套接字连接lsof 还可以显示套接字类型(TCP 或 UDP)以及监听地址和端口(位于名称列中)

举例 2

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
in.telnet 29705 root 2u inet 0x30002808fd8 0t76 TCP aaaaabbbb:telnet->abcdef.bea.com:3886
(ESTABLISHED)

在 HP 上您还可以使用性能监视工具 Glance(可从 http://www.hp.com/ 获得)来分析在运行 WebLogic Server 时所打开文件总数

如果您没有 lsof则还可以在 /proc/<pid>/fd 中查看某个进程所有文件描述符每个文件描述符都驻留在此目录中

Windows 平台

Handle
在 WinNT 或 Windows 2000 上命令行工具 handle 报告有关引用所打开文件句柄信息如下例所示此工具可用于特定进程
它可从以下网址获得:http://www.sysernals.com/ntw2k/freeware/handle.shtml

C:tmp>ps -ef | grep java
usera 1656 1428 0 10:11:41 CONIN$ 0:46 c:ReleasesWLS8.2JDK141~1binjava -client -Xms32m -Xmx200m -XX:MaxPermSize=128m -Xvery:none -Dweblogic.Name=myserver -Dweblogic.ProductionModeEnabled= -Djava.security.policy="c:ReleasesWLS8.2WEBLOG~1serverlibweblogic.policy" weblogic.Server

C:tmp>handle -p java

Handle v2.10
Copyright (C) 1997-2003 Mark Russinovich
Sysernals - www.sysernals.com

------------------------------------------------------------------------------
java.exe pid: 1656 ABCDEFusera
18: File C:ReleasesWLS8.2user_projectsdosmydo
170: File C:ReleasesWLS8.2jdk141_05jrelibrt.jar
178: File C:ReleasesWLS8.2jdk141_05jrelibsunrsasign.jar
180: File C:ReleasesWLS8.2jdk141_05jrelibjsse.jar
188: File C:ReleasesWLS8.2jdk141_05jrelibjce.jar
190: File C:ReleasesWLS8.2jdk141_05jrelibchars.jar
328: File C:ReleasesWLS8.2jdk141_05jrelibextdnsns.jar
330: File C:ReleasesWLS8.2jdk141_05jrelibextldapsec.jar
338: File C:ReleasesWLS8.2jdk141_05jrelibextlocaledata.jar
340: File C:ReleasesWLS8.2jdk141_05jrelibextsunjce_provider.jar
348: File C:ReleasesWLS8.2jdk141_05libtools.jar
350: File C:ReleasesWLS8.2weblogic81serverlibweblogic.jar
358: File C:ReleasesWLS8.2weblogic81serverlibjconn2.jar
360: File C:ReleasesWLS8.2weblogic81serverlibojdbc14.jar
368: File C:ReleasesWLS8.2weblogic81serverlibxmlx.jar
370: File C:ReleasesWLS8.2weblogic81serverlibwebservices.jar
378: File C:ReleasesWLS8.2weblogic81serverlibwlcipher.jar
3e0: File C:ReleasesWLS8.2weblogic81serverlibantant.jar
3e8: File C:ReleasesWLS8.2weblogic81serverlibEccpressoJcae.jar
3f0: File C:ReleasesWLS8.2weblogic81serverlibEccpressoCore.jar
3f8: File C:ReleasesWLS8.2weblogic81serverlibEccpressoAsn1.jar
400: File C:ReleasesWLS8.2weblogic81serverlibjConnect.jar
408: File C:ReleasesWLS8.2weblogic81serverlibantoptional.jar
410: File C:ReleasesWLS8.2weblogic81serverlibantjakarta-oro-2.0.7.jar
….
C:tmp>handle -p java | wc -l
65

这表明在 Windows 上运行 WLS 8.1SP2 时使用了 65 个文件句柄

Process Explorer
Process Explorer 是另个 Windows 工具它是用来监视文件句柄更高级实用它具有 GUI 界面并显示有关正在运行每个进程更多信息您可以使用此来搜索特殊句柄 它可从以下网址获得:http://www.sysernals.com/ntw2k/freeware/procexp.shtml 下面是举例输出屏幕快照:




这表明运行 WLS Java 进程使用 884 个句柄但只有少数(65 个)句柄引用打开文件

通过使用上述任工具您可以确定应当关闭文件是否仍处于打开状态接着您应当按照下面介绍说明方式检查如何关闭文件以及如何释放它文件描述符

返回页首

如何以及何时发布文件描述符?
文件描述符是在文件关闭或进程终止时被淘汰如果 close 系统没有返回失败代码则为将来要分配文件描述符 open 提供相关文件描述符当和某个打开文件描述相关联所有文件描述符已经关闭时该打开文件描述会被释放

您不应当依赖垃圾回收和对象终止功能来释放非 Java 资源(如文件描述符)这就是为什么应当使用 close 以及在出现时处理其输出结果原因

已关闭套接字传输到 TIME_WAIT 以确保所有数据在连接期间被传输最终确认 (ACK) 应当终止数据传输此状态会延迟释放分配给该套接字文件描述符在 Unix 系统上此 TIME_WAIT 期间持续时间在名为 tcp_time_wait _erval 内核参数中定义在 Windows NT、Windows 2000 和 Windows XP 上此期间在注册表中名为 HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters 系统项中定义为 TcpTimedWaitDelay

下面 URL 提供有关 Unix 内核参数详细介绍说明: http://www.unixadm.net/networking/tune.html

返回页首

已知 WebLogic Server 问题
增加文件描述符数量通常将能够解决这种问题但是您还将需要确保 WebLogic Server 作为种应用不使用过多文件还要确保打开文件能够正确关闭以便释放文件描述符

报告给 BEA 客户支持部门所有问题都和缺少文件描述符或者描述符表溢出有关此问题总是在操作系统通知 Java 进程不能分配新文件描述符时发生在这种情况下您需要增加 fd 数量

返回页首

文件描述符和设置

什么是文件描述符?
文件描述符是由无符号整数表示句柄进程使用它来标识打开文件文件描述符和包括相关信息(如文件打开模式、文件位置类型、文件类型等)文件对象相关联这些信息被称作文件上下文

如何创建文件描述符?
进程获取文件描述符最常见思路方法是通过本机子例程 open 或 create 获取或者通过从父进程继承种思路方法允许子进程同样能够访问由父进程使用文件文件描述符对于每个进程般是唯当用 fork 子例程创建某个子进程时该子进程会获得其父进程所有文件描述符副本这些文件描述符在执行 fork 时打开在由 fcntl、dup 和 dup2 子例程复制或拷贝某个进程时会发生同样复制过程

第 2个异常在 JVM 进程缺乏文件描述符时出现(尽管在执行 forkAndExec 子例程时丆需要新文件描述符来复制父进程文件描述符)对于每个进程操作系统内核在 u_block 结构中维护文件描述符表所有文件描述符都在该表中建立索引

如何在区别平台上定义文件描述符数量
文件描述符极限以及可分配给进程最大大小由资源限制来定义这些值应当按照在 WebLogic Server 文档中建议、特定于操作系统文件描述符值来设置:

对于 WLS 8.1:调整硬件、操作系统和网络性能
对于 WLS 7.0:调整硬件、操作系统和网络性能
对于 WLS 6.1:调整硬件、操作系统和网络性能

Unix 和 Linux 都有文件描述符 不过 2者主要区别在于如何设置文件描述符硬极限值、缺省值和配置过程

Solaris
/usr/bin/ulimit 实用定义允许单个进程使用文件描述符数量最大值在 rlim_fd_max 中定义在缺省情况下它设置为 65,536只有 root 用户才能修改这些内核值

Linux
管理用户可以在 etc/security/limits.conf 配置文件中设置他们文件描述符极限如下例所示

soft nofile 1024
hard nofile 4096
系统级文件描述符极限还可以通过将以下 3行添加到 /etc/rc.d/rc.local 启动脚本中来设置:

# Increase system-wide file descriptor limit.
echo 4096 > /proc/sys/fs/file-max
echo 16384 > /proc/sys/fs/inode-max
Windows
在 Windows 操作系统上文件描述符被称作文件句柄在 Windows 2000 服务器上打开文件句柄极限设置为 16,384此数量可以在任务管理器性能摘要中监视

HP-UX
nfile 定义打开文件最大数量此值通常由以下公式来确定:((NPROC*2)+1000)其中 NPROC 通常为:((MAXUSERS*5)+64) 如果 MAXUSERS 等于 400则经过计算得到此值为 5128通常可以将此值设高maxfiles 是每个进程软文件极限maxfiles_lim 是每个进程硬文件极限

AIX
文件描述符极限在 /etc/security/limits 文件中设置缺省值是 2000此极限可以通过 ulimit 命令或 rlimit 子例程来更改最大大小由 OPEN_MAX 常数来定义

返回页首

Tags:  toomanydays toomanytimes toomany toomanyopenfile

延伸阅读

最新评论

发表评论