MappedByteBuffer强制释放后读取引发jvm crash
这几天使用MappedByteBuffer对系统进行了实现,在压测过程中发现启动多个group订阅时服务端会发生jvm crash ,排查后找到了原因,记录一下。
部分信息如下:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x01b8d4d7, pid=10236, tid=8452
#
# JRE version: 6.0_18-b02
# Java VM: Java HotSpot(TM) Client VM (16.0-b09 mixed mode, sharing windows-x86 )
# Problematic frame:
# J java.nio.DirectByteBuffer.get(I)B
#
# An error report file with more information is saved as:
# D:\workspace_new\metamorphosis\metamorphosis-server\hs_err_pid10236.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#
原因是在MappedByteBuffer释放后再对它进行读操作的话就会引发这个crash,在并发情况下很容易正在释放时另一个线程正开始读取,于是crash就发生了。下面这个测试代码可以重现:
@Test
public void unmapAndRead()throws Exception {
File file =new File("unmapAndRead.txt");
FileChannel fileChannel =new RandomAccessFile(file,"rw").getChannel();
MappedByteBuffer buf = fileChannel.map(MapMode.READ_WRITE, 0, 4096);
buf.putInt(5);
buf.force();
this.unmap(buf);
buf.get(2);//Crash occur
}
void unmap(finalMappedByteBuffer mappedByteBuffer) {
try {
if (mappedByteBuffer ==null) {
return;
}
mappedByteBuffer.force();
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
Method getCleanerMethod = mappedByteBuffer.getClass().getMethod("cleaner",new Class[0]);
getCleanerMethod.setAccessible(true);
sun.misc.Cleaner cleaner =
(sun.misc.Cleaner)getCleanerMethod.invoke(mappedByteBuffer,new Object[0]);
cleaner.clean();
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
});
}
catch (Exception e) {
e.printStackTrace();
}
}
上一篇: Android自定义ListFragment 显示
下一篇: 4项技巧使你不再为PHP中文编码苦恼,