昨天项目上线的时候,服务器程序在读写文件的类中,频繁出现IOException---Too many open files的问题,出现这个问题的原因是:当前打开的文件句柄数超过了系统的默认值,调大系统的默认文件句柄数,程序正常,但是运行了一段时间后,程序再次出错,使用lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|grep pid命令进行查看,发现程序占用了大量的文件句柄,并且句柄值有不断上升的趋势,于是查看程序代码,看看是否存在文件读写未关闭流的情况,最后将问题定位到如下代码(程序中使用了Properties来读写文件,操作即为频繁):
Properties fidPro = new Properties();
fidPro.load(new FileInputStream(file));
当时调用Properties的load方法的时候理所当然地认为当前使用完传入的inputStream后,会将其关闭,但是当我查看其源码的时候发现里面并没有关闭inputStream的操作,将代码修改为如下:
Properties fidPro = new Properties();
FileInputStream fis = new FileInputStream(file);
fidPro.load(fis);fis.close();
在网上找到的例子大多没有主动关闭输入流,不过因为此类主要是用作读取配置使用,不会频繁读写,也不会造成太多问题。和我的场景不同。查看oracle的官方文档,发现其已指明:
public void load(InputStream inStream)
throws IOException
Reads a property list (key and element pairs) from the input byte stream. The input stream is in a simple line-oriented format as specified in load(Reader) and is assumed to use the ISO 8859-1 character encoding; that is each byte is one Latin1 character. Characters not in Latin1, and certain special characters, are represented in keys and elements using Unicode escapes as defined in section 3.3 of The Java™ Language Specification.
The specified stream remains open after this method returns.
此方法返回后,输入流依旧是打开的。
StackOverflow还有相关的讨论:
http://stackoverflow.com/questions/40078141/the-properties-load-would-close-the-inputstream