本章では、java.ioパッケージと、java.netパッケージによる入出力を高速化するための技術である、 チャネル技術について記述します。
java.ioパッケージで普段行っている様なファイルへの読み込み、 書き出し、ソケットへの読み込み、書き出し等の操作は、 幾つかの概念の層を組み合わせることにより、実現されています。
+-----------------------------+
| readメソッド、writeメソッド |
+-----------------------------+
^
| データの提供
|
+------InputStream, OutputStream ------+
| +--------------------------+ |
| | データ変換の層 | |
| +------------------------------+ |
| | バッファリングの層 | |
| +----------------------------------+ |
| | 入出力の層 | |
| +----------------------------------+ |
+--------------------------------------+
まず、入出力の層ですが、これは実際に開いたストリームを制御し、JavaVM環境の壁を越えて、 システムと実質上の読み込みと書き出し機能を提供します。
次に、バッファリングの層ですが、入力の場合、入出力の層の層で読み込んだデータを、 一時的にバッファに貯めておき、プログラムの要求に応じて、バッファからデータを取り出します。 出力の場合は、入出力の層で書き出す前に、ある程度のサイズのデータをバッファに溜めておき、 一定量まで溜まるか、flush命令がされたときに、まとめて出力を行います。 これらの振る舞いは、バッファの使用を意図していない場合でも、勝手にシステムやAPIが最適化として行っています。
入出力の層、バッファリングの層を経たデータは、byteの並びの状態です。 そのデータは、データ変換の層によって、 特定の文字コードに符号化されたり数値に直されたりして、 プログラムにとって意味のあるデータに変換されます。
このようなjava.ioの構造は、意味的には非常に理解しやすく、まさにオブジェクト指向の設計です。 しかし、入出力を行う時には常に、この2層あるいは3層を経由し、 各層を通過するときに、データのコピーが毎回行われます。
しかも内部的にバッファリングされているInputStreamやOutputStreamを、 BufferedInputStreamやBufferedOutputStreamでラップすることにより、 結果的には速度が速くなるものの、内部的には、さらにバッファへのデータのコピーが発生します。 つまり、 意味のないコピーが処理の途中で度々起こっており、 効率としてはあまりいいとは言えません。
チャネル(channel)の技術は、java.ioやjava.net等に見られた、 意味のないデータの連鎖的コピーを解消することで、 データ転送の速度を上げようというもの です。
チャネルの技術は、java.ioでいうところの、入出力の層をjava.nio.channels(チャネル)で、 バッファリングとデータ変換の層をjava.nio(バッファ)で管理します。
本章では、このチャネルとバッファについての使い方を記述します。