У меня есть очень большой массив парных разрядов, в котором я использую диск-файл и пейджинговый список MappedByteBuffers для обработки, см. this question для получения дополнительной информации. Я работаю в Windows XP с использованием Java 1.5.Почему я получаю «Недостаточно памяти для обработки этой команды» с использованием Java MappedByteBuffers?
Вот ключевая часть моего кода, который делает выделение буферов против файла ...
try
{
// create a random access file and size it so it can hold all our data = the extent x the size of a double
f = new File(_base_filename);
_filename = f.getAbsolutePath();
_ioFile = new RandomAccessFile(f, "rw");
_ioFile.setLength(_extent * BLOCK_SIZE);
_ioChannel = _ioFile.getChannel();
// make enough MappedByteBuffers to handle the whole lot
_pagesize = bytes_extent;
long pages = 1;
long diff = 0;
while (_pagesize > MAX_PAGE_SIZE)
{
_pagesize /= PAGE_DIVISION;
pages *= PAGE_DIVISION;
// make sure we are at double boundaries. We cannot have a double spanning pages
diff = _pagesize % BLOCK_SIZE;
if (diff != 0) _pagesize -= diff;
}
// what is the difference between the total bytes associated with all the pages and the
// total overall bytes? There is a good chance we'll have a few left over because of the
// rounding down that happens when the page size is halved
diff = bytes_extent - (_pagesize * pages);
if (diff > 0)
{
// check whether adding on the remainder to the last page will tip it over the max size
// if not then we just need to allocate the remainder to the final page
if (_pagesize + diff > MAX_PAGE_SIZE)
{
// need one more page
pages++;
}
}
// make the byte buffers and put them on the list
int size = (int) _pagesize ; // safe cast because of the loop which drops maxsize below Integer.MAX_INT
int offset = 0;
for (int page = 0; page < pages; page++)
{
offset = (int) (page * _pagesize);
// the last page should be just big enough to accommodate any left over odd bytes
if ((bytes_extent - offset) < _pagesize)
{
size = (int) (bytes_extent - offset);
}
// map the buffer to the right place
MappedByteBuffer buf = _ioChannel.map(FileChannel.MapMode.READ_WRITE, offset, size);
// stick the buffer on the list
_bufs.add(buf);
}
Controller.g_Logger.info("Created memory map file :" + _filename);
Controller.g_Logger.info("Using " + _bufs.size() + " MappedByteBuffers");
_ioChannel.close();
_ioFile.close();
}
catch (Exception e)
{
Controller.g_Logger.error("Error opening memory map file: " + _base_filename);
Controller.g_Logger.error("Error creating memory map file: " + e.getMessage());
e.printStackTrace();
Clear();
if (_ioChannel != null) _ioChannel.close();
if (_ioFile != null) _ioFile.close();
if (f != null) f.delete();
throw e;
}
Я получаю сообщение об ошибке, указанной в названии после выделяю второй или третий буфер.
Я думал, что это связано с непрерывной памятью, поэтому попробовали ее с разными размерами и количеством страниц, но не в полной мере.
Что именно делает «Недостаточно хранения для обработки этой команды» означает, и что, если можно, я могу сделать с этим?
Я думал, что точка MappedByteBuffers была способностью обрабатывать структуры, большие, чем вы могли бы вместить в кучу, и относиться к ним так, как если бы они были в памяти.
Любые подсказки?
EDIT:
В ответ на ответ ниже (@adsk) Я изменил мой код, поэтому я никогда не иметь более одного активного MappedByteBuffer в любое время. Когда я ссылаюсь на область файла, который в настоящее время не отображается, я удаляю существующую карту и создаю новую. Я по-прежнему получаю ту же ошибку после примерно трех операций карты.
Ошибка, указанная в GC, не собирающем MappedByteBuffers, по-прежнему кажется проблемой в JDK 1.5.
Перед тем, как сделать вывод о том, что GC ошибка все еще существует, вам нужно запустить свой код через профайлер использования памяти, чтобы убедиться, что его не висит на ссылки ByteBuffer. –