Java 性能优化实战记录(2)---句柄泄漏和监控
前言: Java不存在内存泄漏, 但存在过期引用以及资源泄漏. (个人看法, 请大牛指正)
这边对文件句柄泄漏的场景进行下模拟, 并对此做下简单的分析.
如下代码为模拟一个服务进程, 忽略了句柄关闭, 造成不能继续正常服务的小场景.
1 public class FileHandleLeakExample { 2 3 public static String readContentFromFile(String filename) { 4 StringBuilder sb = new StringBuilder(); 5 BufferedReader br = null; 6 try { 7 br = new BufferedReader(new FileReader(filename)); 8 String line = null; 9 while ( (line = br.readLine()) != null ) { 10 sb.append(line).append("\n"); 11 } 12 } catch (Exception e) { 13 System.err.println(e.getMessage()); 14 exit(1); 15 } finally { 16 // 模拟疏忽关掉句柄的操作 17 // try { 18 // br.close(); 19 // } catch (IOException e) { 20 // e.printStackTrace(); 21 // } 22 } 23 return sb.toString(); 24 } 25 26 public static void main(String[] args) { 27 while ( true ) { 28 FileHandleLeakExample.readContentFromFile("1.txt"); 29 } 30 } 31 32 } 33 34 /* 35 输入结果如下: 36 1.txt (Too many open files) 37 */
句柄泄漏导致, 进程服务达到系统设置的上限, 进而导致不可服务状态. 这就需要必要的监控了.
如何监控或者如何在测试阶段能提前发现呢?
在linux中, 一切皆句柄, 比如file, socket都是, 每个进程都有自己的上限, 一旦超过这个上限,系统就会限制并拒绝相应的资源请求.
这个设定如下所示:
ulimit -a # ulimit -n 列出open file的个数
由此可见系统对于一般进程的文件句柄上限为 1024.
但对上面那个java进程进行观察, 却发现如下不一致的地方,如下所示:
jps #列出java进程的pid列表
cd /proc/<pid>/fd #通过linux的虚拟文件系统,进入该java进程的系统信息
ls | wc -l #统计其总开打开的文件句柄数
其拥有的句柄个数4095与系统限制的句柄数上限1024相差太远, 这是什么情况?
实际上系统的限制, 分为两种,一种为soft limit, 另一种为hard limit, soft limit相当于一个warning, 而hard limit系统则不允许超越.
执行如下命令:
ulimit -a -H # ulimit -n -H 列出open file的句柄数
现在系统的open file 4096的上限与java进程拥有的句柄数4095保持了一致.
关于soft limit和hard limit的区别, 请参阅如下链接:
http://blog.163.com/zhangjie_0303/blog/static/9908270620112233523316/
对于文件句柄数, 还可以借用lsof命令来查阅
lsof -p <pid>
posted on 2014-04-24 19:30 mumuxinfei 阅读(3814) 评论(5) 编辑 收藏 举报