昨日の PrintWriter の件

昨日のPrintWriterの件に激しく誤解した「仕様です」との指摘が来たので説明ついでに検証しておく。
別に、生成したストリームを全部、個別に close しないといけないといったわけじゃなくて、

writer = new OutputStreamWriter(new FileOutputStream(file), encoding);

だと、invalid なエンコーディングを指定された場合に、OutputStreamWriter のコンストラクタが UnsupportedEncodingException を投げるわけで、そのとき writer は null になると。で、その場合、すでに生成された FileOutputStream のインスタンスがどこからも参照されていないので、close できないという話。
で、一応検証。プラットフォームは FreeBSD

% cat PrintWriterTest.java
import java.io.File;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class PrintWriterTest {
    public static void main(String[] args) throws IOException {
        File dir = new File("tmp");
        String encoding = "dummy";

        if (!dir.exists()) {
            dir.mkdirs();
        }

        for (int i = 0; i < 1000; i++) {
            String filename = String.format("%05d", i);
            File file = new File(dir, filename);
            PrintWriter out = null;

            try {
                out = new PrintWriter(file, encoding);
            } catch (UnsupportedEncodingException ex) {
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        }
    }
}
% javac PrintWriterTest.java
% ulimit -n 30
% java PrintWriterTest
Exception in thread "main" java.io.FileNotFoundException: tmp/00176 (Too many open files)
        at java.io.FileOutputStream.open(Native Method)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:179)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:131)
        at java.io.PrintWriter.<init>(PrintWriter.java:252)
        at PrintWriterTest.main(PrintWriterTest.java:21)

同時オープン数を30に制限したはずなのに 177 回目で「Too may open files」になるのがかなり謎ではあるが(finalizerがなにかしているのかも)、やっぱりバグですな。