mck*_*mey 17 java file-io java-7
我已经查看了关于SO的其他类似问题,但它们似乎是由其他问题引起的.
首先,我确保我明智地关闭了所有文件句柄,然后我常常lsof -p <pid of java>查看我的文件列表.
它在整个运行时间内保持相当稳定,但随后定期我会得到大约10,000个条目,lsof如下所示:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
...
java 36809 smm *235r PSXSEM 0t0 kcms00008FC901624000
java 36809 smm *236r PSXSEM 0t0 kcms00008FC901624000
java 36809 smm *237r PSXSEM 0t0 kcms00008FC901624000
java 36809 smm *238r PSXSEM 0t0 kcms00008FC901624000
java 36809 smm *239r PSXSEM 0t0 kcms00008FC901624000
Run Code Online (Sandbox Code Playgroud)
手册页说PSXSEM类型是POSIX信号量.JDK使用POSIX信号量的任何线索?顺便说一句,该应用程序目前是一个单线程命令行应用程序.
潜在有用的背景:我在Mac OS X 10.7.3上升级到JDK 1.7后首先注意到这一点:
java version "1.7.0_04"
Java(TM) SE Runtime Environment (build 1.7.0_04-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)
Run Code Online (Sandbox Code Playgroud)
更新:$JAVA_HOME在JDK 1.6上重新编写似乎是该问题的解决方法.
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)
Run Code Online (Sandbox Code Playgroud)
什么是JDK 1.7做得与众不同?
我能够将其追溯到这段代码:
BufferedImage image = null;
ImageInputStream stream = null;
try {
stream = new FileImageInputStream(file);
image = ImageIO.read(stream);
} catch (Exception ex) {
log.error("Image could not be read: "+file.getPath());
} finally {
// ImageIO closes input stream unless null is returned
// http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#read(javax.imageio.stream.ImageInputStream)
if (stream != null && image == null) {
try {
stream.close();
} catch (IOException ex) {
log.error("ERROR closing image input stream: "+ex.getMessage(), ex);
}
}
}
Run Code Online (Sandbox Code Playgroud)
JavaDocs特别指出这种方法(与其他方法不同)会自动关闭流.实际上,当您尝试手动关闭它时,它会抛出一个说"关闭"的异常.我正在使用这个重载,因为另一个说它ImageInputStream无论如何包装它所以我以为我会节省一些工作.
更改块以使用正常FileInputStream修复泄漏:
BufferedImage image = null;
InputStream stream = null;
try {
stream = new FileInputStream(file);
image = ImageIO.read(stream);
} catch (Exception ex) {
log.error("Image could not be read: "+file);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ex) {
log.error("ERROR closing image input stream: "+ex.getMessage(), ex);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这在我看来是JDK 1.7中的一个错误,因为1.6在这里运行良好.
更新:我刚刚向 Oracle 提交了一个针对此问题的错误报告.