当我调试我的应用程序时,我终于找到了问题。我可以重现它,但我不知道它为什么会发生。这是整个代码:
public static MappedByteBuffer map(File file, long length) throws IOException {
RandomAccessFile raf = new RandomAccessFile(file, "rw");
try {
if (length > 0) {
raf.setLength(length);
}
try {
return raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, file.length());
} catch (IOException e) {
System.gc();
System.runFinalization();
return raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, file.length());
}
} finally {
raf.close();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
long t = System.currentTimeMillis();
MappedByteBuffer mbb = map(new File("temp.mmp"), 1024L * 1024 * 1024);
System.out.println("load " + (System.currentTimeMillis() - t));//*
for (int i = 0; i < 2014L * 1024 * 1024; i++) {}//*
int d = 0;
for (int j = 0; j < 10; j++) {
t = System.currentTimeMillis();
mbb.position(0);
mbb.limit(mbb.capacity());
for (int i = 0; i < mbb.capacity(); i++) {
d += mbb.get();
}
System.out.println(j + " " + (System.currentTimeMillis() - t));
}
System.out.println(d);
}
输出结果为:
load 3
0 3429
1 3443
2 3203
3 3197
4 3203
5 3194
6 3247
7 3216
8 3211
9 3201
-1073741824
在注释掉标有//*
的两行后,输出为:
0 782
1 804
2 539
3 557
4 545
5 558
6 546
7 546
8 545
9 557
-1073741824
我在JDK 6/7/8和Windows7 64 OS下测试过,没有区别。但是在linux / CentOS下,问题就消失了。这是一个Java bug吗?或者我做错了什么。谢谢你的帮助。
经过深入研究,我了解到这是关于JIT的事情。但我还是不知道为什么。
新的测试代码:
public static void main(String args[]) {
System.out.println("a");//1
for (int i = 0; i < 1073741824; i++) {}//2
{
long d = 0;
long t = System.currentTimeMillis();
for (int j = 0; j < 40; j++) {
for (int x = 0; x < 1073741824; x++) {
d += 1;
}
}
System.out.println(d + " " + (System.currentTimeMillis() - t));
}
{
long d = 0;
long t = System.currentTimeMillis();
for (int j = 0; j < 40; j++) {
for (int x = 0; x < 1073741824; x++) {
d += 1;
}
}
System.out.println(d + " " + (System.currentTimeMillis() - t));
}
}
输出是:
a
42949672960 792
42949672960 1563
评论/取消注释// 1或// 2的行将影响结果。奇怪的事情。