# !/bin/bash
COUNTER=0
HOW_MANY=0
MAX=0
# do not take care about COUNTER - just flag, shown should we continie or not
while [ $COUNTER -lt 10 ]; do
#run until process with passed pid alive
if [ -r "/proc/$1" ]; then
# count, how many files we have
HOW_MANY=`/usr/sbin/lsof -p $1 | wc -l`
#output for live monitoring
echo `date +%H:%M:%S` $HOW_MANY
# uncomment, if you want to save statistics
#/usr/sbin/lsof -p $1 > ~/autocount/config_lsof_`echo $HOW_MANY`_`date +%H_%M_%S`.txt
# look for max value
if [ $MAX -lt $HOW_MANY ]; then
let MAX=$HOW_MANY
echo new max is $MAX
fi
# test every second. if you don`t need so frequenlty test - increase this value
sleep 1
else
echo max count is $MAX
echo Process was finished
let COUNTER=11
fi
done
12条答案
按热度按时间sbtkgmzw1#
当我需要测试ic计数时,这个小脚本帮助我保持打开文件的计数。如果是在linux上使用的,那么对于solaris您应该修补它(可能是:)
你也可以试着玩jvmontion-xverify:none - 它应该禁用jar验证(如果大多数打开的文件是jars…)。对于通过未关闭的fileoutputstream进行的泄漏,您可以使用findbug(以上指导)或尝试查找如何修补标准java fileoutputstream/fileinputstream的文章,在这里您可以看到谁打开了文件,谁忘记了关闭它们。不幸的是,现在找不到这篇文章,但这是存在的:)还要考虑一下文件限制的增加-对于最新的*nix内核处理1024fd以上不是问题。
1aaf6o9v2#
它肯定能给你一个主意。因为它是java,所以文件打开/关闭机制应该以类似的方式实现(除非其中一个jvm实现不正确)。我建议在windows上使用文件监视器。
xt0899hw3#
我发现了一个跟踪未关闭文件句柄的好方法,那就是findbugs:
http://findbugs.sourceforge.net/
它检查许多事情,但其中最有用的是资源打开/关闭操作。它是一个在源代码上运行的静态分析程序,也可以作为eclipse插件使用。
neekobn84#
这是一种帮助查找未关闭资源的编码模式。它关闭资源,并在日志中抱怨问题。
将上述file.close()调用 Package 到忽略错误的try catch块中。
另外,Java7有一个新的“try with resource”特性,可以自动关闭资源。
pvabu6sv5#
首先,我会要求我的系统管理员为进程获取所有打开的文件描述符的列表。不同的系统以不同的方式实现这一点:例如,linux具有
/proc/PID/fd
目录。我记得solaris有一个命令(可能是pfiles?)可以做同样的事情——您的系统管理员应该知道它。但是,除非您看到对同一个文件的大量引用,否则fd列表不会对您有所帮助。如果它是一个服务器进程,那么它可能会因为某种原因打开很多文件(和套接字)。解决此问题的唯一方法是调整打开文件的系统限制—您也可以使用ulimit检查每个用户的限制,但在大多数当前安装中,该限制等于系统限制。
rqmkfv5c6#
我会在你的solaris框中再次检查环境设置。我相信在默认情况下,solaris每个进程只允许256个文件句柄。对于服务器应用程序,尤其是在专用服务器上运行的应用程序,这是非常低的。图50或更多用于打开jre和库jar的描述符,然后至少为每个传入请求和数据库查询提供一个描述符,可能更多,您可以看到这不会减少严重服务器的负担。
看一看这个
/etc/system
文件,用于rlim_fd_cur
以及rlim_fd_max
,以查看系统设置了什么。然后考虑这是否合理(您可以看到服务器运行时打开了多少文件描述符)lsof
命令,最好使用-p[process id]参数。pepwfjgg7#
从系统内部搜索名为filemon的应用程序。
顺便说一句,为了追踪这一点,您可以使用aspectj之类的工具来记录所有打开和关闭文件的调用,并记录它们发生的位置。
uplii1fm8#
在windows上,可以使用process explorer查看打开的文件句柄:
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
在solaris上,可以使用“lsof”监视打开的文件句柄
muk1a3rh9#
在您的情况下,这可能不太实际,但当我在开放数据库连接方面遇到类似问题时,我曾经做过的是用我自己的函数覆盖“open”函数(方便的是,我已经有了这个函数,因为我们已经编写了自己的连接池。)然后在我的函数中,我向一个记录打开的表添加了一个条目。我做了一个堆栈跟踪调用,并保存了调用方的标识,以及调用的时间,我忘记了还有什么。当连接被释放时,我删除了表条目。然后我有了一个屏幕,我们可以转储打开的条目列表。然后您可以查看时间戳,很容易地看到哪些连接已经打开了不太可能的时间,哪些函数已经完成了这些打开。
从这一点上,我们能够快速跟踪到打开连接和关闭连接失败的两个函数。
如果您有许多打开的文件句柄,那么很有可能在某个地方完成操作时无法关闭它们。你说你已经检查了正确的try/finally块,但是我怀疑代码中的某个地方你要么漏掉了一个错误的块,要么你有一个函数,但从来没有到达finally。我想也有可能每次打开一个文件时都会进行适当的关闭,但同时打开的文件有数百个。如果是这样的话,我不知道你能做什么,除了一个严肃的程序重新设计来操作更少的文件,或一个严肃的程序重新设计来排队你的文件访问(在这一点上,我添加了通常的“不知道您的应用程序的细节等。)
kognpnkq10#
值得记住的是,在unix系统上,opensocket还使用文件句柄。因此,很可能是数据库连接池泄漏(例如,打开的数据库连接未关闭并返回到池)导致了此问题-当然,我以前见过由连接池泄漏导致的此错误。
ecfsfe2w11#
不是对您的问题的直接回答,但这些问题可能是由于在遗留代码中错误地释放文件资源而导致的。举例来说,如果使用fileoutputsstream类,请确保在finally块中调用close方法,如本例所示:
wnvonmuf12#
回答问题的第二部分:
什么会导致打开的文件句柄耗尽?
很明显,打开了很多文件,却没有关闭它们。
最简单的情况是,对持有本机句柄的任何对象的引用(例如。,
FileInputStream
)在关闭之前被丢弃,这意味着文件在对象完成之前保持打开状态。另一个选择是对象存储在某个地方,而不是关闭。堆转储可以告诉你什么东西在哪里逗留(
jmap
以及jhat
包含在jdk中,或者您可以使用jvisualvm
如果您需要gui)。您可能对查找拥有的对象感兴趣FileDescriptor
s。