Subscribed unsubscribe Subscribe Subscribe

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

Java 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 でもなんとかして落としたい。