2014-11-09 6 views
2

У меня было жесткое временное отображение памяти в 550 МБ-файле. Я понимаю, что 32-разрядная JVM может выделить максимальный объем памяти около 1,4 Гб, поэтому мне нужно сопоставить большой файл по частям. Однако это 550 МБ файл, но я все еще не могу отобразить все это в памяти. Лучшее, что я могу сделать, это размер буфера около 333 МБ.32-разрядный максимальный размер памяти JVM на 64-битной Windows не так важен, как ожидалось

Ниже мой тестовый код:

void testMap() throws IOException{ 
    long buffer = 500000000; // CAUSES ERROR. best I can do is 350000000 
    RandomAccessFile srcFile = new RandomAccessFile("550MBFile", "r"); 
    ByteBuffer srcbb = srcFile.getChannel().map(MapMode.READ_ONLY, 0, buffer); 
} 

И ошибка заключается в следующем:

Exception in thread "main" java.io.IOException: Map failed at sun.nio.ch.FileChannelImpl.map(Unknown Source) at TestSpliter.testMap(TestSpliter.java:22) at TestSpliter.main(TestSpliter.java:14) Caused by: java.lang.OutOfMemoryError: Map failed ...

JVM аргумент: -Xms1024m

Может кто-нибудь объяснить, почему я могу использовать только 300MB из 1,4 ГБ? Благодарю.

Обратите внимание, что это не дублирующий вопрос с теми, кто спрашивает о максимальном размере кучи для 32-разрядной JVM.

+1

Почему вы не можете использовать 64-битную JVM? – immibis

+1

@immibis: Возможно, «потому что IT говорит так» ... –

+0

@immibis Просто создайте новый ПК с Windows 8.1 и проверите пару старых кодов. Java.com обеспечивает 32-разрядную загрузку для Win8 по умолчанию, поэтому я думаю, было бы здорово, если мое приложение сможет поддерживать 32-разрядную JVM. На самом деле, я думаю, что проблема здесь не в том, что 32-разрядная проблема, так как фактическое адресное пространство, которое я получаю, намного меньше прогнозируемых возможностей. – Fenwick

ответ

3

Возможно, ваше адресное пространство является фрагментированным и доступно не более 550 МБ свободного пространства. Если вам нужны большие карты памяти, вы должны иметь возможность отображать их в сегментах, если это становится необходимым.

+0

Спасибо за ответ. Я не уверен, как именно JVM выделяет память, но, согласно нескольким сообщениям здесь, на SO, JVM выделяет большую смежную область памяти максимального размера. Разве это не означает, что в программах Java гарантируется область смежного адресного пространства, размер которой примерно равен размеру JVM? Другими словами, если JVM можно инициализировать, вероятно, будет достаточно смежного адресного пространства? – Fenwick

+0

@Fenwick Это зависит от платформы. Например, на некоторых платформах библиотеки загружаются по фиксированному адресу, если этот адрес доступен, чтобы улучшить совместное использование страниц и минимизировать перемещения. Это может означать, что память сильно фрагментирована только тогда, когда процесс, наконец, начинается. Если возможно, переходите к 64-битным. –

+2

@Fenwick Если JVM может быть инициализирован, и он выделяет кучу 1 ГБ, то там * * 1 ГБ непрерывного неиспользуемого пространства. Но 1GB больше не используется, потому что куча использует его. – immibis