質問: reader.readLine(); outBuf.append(line + " "); } // ログ出力 logger.debug("ファイル属性変更結果:" + ファイル名 + " " + outBuf.toString()); } catch (InterruptedException e) { logger.debug("ファイル属性変更失敗:" + e.getMessage()); } catch (IOException ex){ logger.debug("ファイル属性変更失敗:" + e.getMessage()); } catch (Exception ex){ logger.debug("ファイル属性変更失敗:" + e.getMessage()); } finally { ; } ``` ### 試したこと ■ファイルディスクリプタの増加を検証 <コマンド> ls /proc/実行しているTomcatのプロセスID/fd | wc -l <結果> プログラム実行前:209 プログラム実行完了直後:211 →[socket:xxxx]というファイルディスクリプタが2件増加 プログラム実行完了から数秒経過後:209 →増えた[socket:xxxx]という2件が減少。プログラム実行前と同じ状態 ### その他気になっていること process.getInputStream()では標準入出力ストリーム、標準エラー出力ストリームから渡される、とJavadocに記載があるので、 ファイルディスクリプタ#0、#1、#2は標準で使用されているから、そもそも閉じなくてはいいのでは?と思ったが、 ネットで調べると、3つのストリームは使用するしないに関わらずcloseしてくださいとあるので、 自分のファイルディスクリプタに対する認識が誤っていそうな。。 ### 補足情報(FW/ツールのバージョンなど) OS: Red Hat Enterprise Linux Server release 6.5 JRE: 1.7.0_45 JVMの再起動は年に数回程度のため、JVM再起動によるファイルディスクリプタの解放は考えにくいです。
回答: <検証> プログラムに該当処理の前後にThread.sleep()を入れ、sleep中に該当プロセスにおけるファイルディスクリプタを変動を確認する。 <検証手順> 1.ソースにThreep.sleep()(とログ出力)を追加 ``` //属性変更のコマンド String processCommand = "chmod 666 " + ファイル名 + " 2>&1 ; echo $? "; try{ // コマンド実行 Thread.sleep(60000); logger.info("コマンド実行前"); Process process = Runtime.getRuntime().exec(processCommand); Thread.sleep(60000); logger.info("コマンド実行後"); process.waitFor(); // ストリームを取得 Thread.sleep(60000); logger.info("process.getInputStream実行前"); InputStream inputStream = process.getInputStream(); Thread.sleep(60000); logger.info("process.getInputStream実行後"); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); Thread.sleep(60000); logger.info("BufferedReader実行後"); ``` 2.該当プロセスの確認 今回はTomcat上で動いているプロセスのため、 ``` ps -ef | grep tomcat ``` でプロセスIDを取得。 3.プログラムの実行 4.ファイルディスクリプタの確認 sleep処理実行中、linuxにて ``` ls -ltr /proc/プロセスID/fd ``` を実行し、sleepを入れいているタイミングごとの変更を確認。 5.すべてのsleep時に確認した「4.」の実行結果を比較し、ファイルディスクリプタの変遷を確認。 <結果確認> ファイルディスクリプタの増加は確認できなかった。以下が考えられる。 * ファイルディスクリプタは作成されない * ファイルディスクリプタは作成されたが、chmodの処理完了後、即解放されている