Sun JVM の MappedByteBuffer は、途中でデバイスにアクセスできなくなると落ちるらしい。

という記事がikvmブログの記事にあった。

Running this on JDK 1.6 (x64) and removing the network cable during the sleep will result in an Internal Error in the VM. Not exactly what I had hoped for.

Interestingly, on IKVM doing the same results in a cli.System.Runtime.InteropServices.SEHException being thrown.

.NET Frameworkの方はちゃんと例外を投げるようになっているっぽい。

で、やってみた。

まずは Windows から Debian GNU/Linux で動いている Samba につなぎにいき、途中で samba を止める。

import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.MappedByteBuffer;

public class MMapTest {
	public static void main(String[] args) throws Exception {
		FileChannel fc = new RandomAccessFile("\\\\roadrunner\\moriyoshi\\Desktop\\test.txt", "r").getChannel();
		Thread.sleep(10000);
		MappedByteBuffer map = fc.map(FileChannel.MapMode.READ_ONLY, 0, 4096);
		System.out.println(map.get(8));
	}
}

結果:

C:\>java MMapTest

#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  EXCEPTION_IN_PAGE_ERROR (0xc0000006) at pc=0x6d783d0c, pid=3084, tid=3852
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_06-b05 mixed mode, sharing)
# Problematic frame:
# V  [jvm.dll+0x113d0c]
#
# An error report file with more information is saved as hs_err_pid3084.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

ぎゃー、確かに落ちる。逆はどうだろう。mount.cifs でマウントしてやってみた。

Sun JVM:

% LANG=C java MMapTest
Exception in thread "main" java.io.IOException: Input/output error
        at sun.nio.ch.FileChannelImpl.size0(Native Method)
        at sun.nio.ch.FileChannelImpl.size(FileChannelImpl.java:310)
        at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:728)
        at MMapTest.main(MMapTest.java:9)

gcj (GNU Classpath):

% LANG=C java MMapTest
Exception in thread "main" java.io.IOException: Input/output error
   at gnu.java.nio.channels.FileChannelImpl.mapImpl(libgcj.so.70)
   at gnu.java.nio.channels.FileChannelImpl.map(libgcj.so.70)
   at MMapTest.main(MMapTest.java:9)

smbfs の場合は、どの段階でかは分からないけど一定時間はブロックして (「刺さって」)、そのあとエラーを返すようになっていますね。今日は深追いするのはやめておこう。

ちなみに、このバグ、Bug #6415680として登録されていました。

追記: FileChannel.size() で落ちるか落ちないかが運命の境目と見た。smbfs でもなんとかして落としたい。