マルチプラットフォームなJavaでプラットフォームに依存するバグにぶちあたりちょっと困った事になった。

プログラム自体はなんてことないFileInputStreamを使ったファイルの読み取り処理。
開発機であるWindowsではもちろん正常に動作していたんですが
環境が変わったときに問題が発生してしまいました。

[環境]

// コードはサンプルです
FileInputStream fis = null;
try {
	fis = new FileInputStream(path);

	/*** 中略 ***/

	Closeable closeable = fis;
	Channel channel = ((FileInputStream) closeable).getChannel();
	if (channel.isOpen()) {
		closeable.close();
	}
} catch (Exception e) {
	throw new Exception(e);
}

これを実行するとFileInputStreamのclose処理で落ちてしまいます。

Caused by: java.io.IOException: Bad file number
at sun.nio.ch.FileDispatcher.preClose0(Native Method)
at sun.nio.ch.FileDispatcher.preClose(Unknown Source)
at sun.nio.ch.FileChannelImpl.implCloseChannel(Unknown Source)
at java.nio.channels.spi.AbstractInterruptibleChannel.close(Unknown Source)
at java.io.FileInputStream.close(Unknown Source)

RHELで動かしてみても以下のエラーが発生。

[環境]

  • RHEL5.5(2.6.18-194.el5)
  • jre1.6.0_20

Caused by: java.io.IOException: Bad file descriptor
at sun.nio.ch.FileDispatcher.preClose0(Native Method)
at sun.nio.ch.FileDispatcher.preClose(Unknown Source)
at sun.nio.ch.FileChannelImpl.implCloseChannel(Unknown Source)
at java.nio.channels.spi.AbstractInterruptibleChannel.close(Unknown Source)
at java.io.FileInputStream.close(Unknown Source)

sun bug databaseからそれらしきものを拾ってくると、此処らへんになるのかなぁ…
Bug ID: JDK-6322678 FileInputStream(FileDescriptor) throws IOException when reading a file if FD is invalid
Bug ID: JDK-6359397 FileInputStream.read() and FileOutputStream.write() throw IOException: No such file or directory

FileInputStream(FileDescriptor) throws IOException when reading a file if FD is invalid辺りはそれっぽいですが、これはこれでまた別の事象なような。
ちなみに、この問題はjre1.6.0_25で一応解決してるとのことでしたので、早速jreを入れ替えて試してみると

………動いた。

はて、これでいいのかな… と思いつつも今回はこれ以上調査する時間もないのでまた時間があるときに調べてみよう。


【追記】
http://256.com/gray/docs/misc/java_bad_file_descriptor_close_bug.shtml
上記サイトにはRandomAccessFile.seek()、FileInputStream.readBytes()で落ちると例で書かれていたので試してみましたが正常に動きますねぇ…まあ、バージョン違うんですけど。
今のところFileInputStream.close()以外では問題は発生していないみたい。