Знаете ли вы, что можно выделять сегменты памяти, которые больше, чем физический размер оперативной памяти вашего компьютера, и даже больше, чем размер всей вашей файловой системы? Прочтите эту статью и узнайте, как использовать сопоставленные (mapped) сегменты памяти, которые могут быть или не быть «разреженными», и как выделить 64 терабайта разреженных данных на ноутбуке. Сопоставленная память — это виртуальная память, которой было назначено взаимно-однозначное сопоставление с частью файла. Термин «файл» используется здесь в довольно широком смысле и может быть представлен обычным файлом, устройством, общей памятью или любым другим объектом, на который операционная система может ссылаться через дескриптор файла. Доступ к файлам через сопоставленную память часто намного быстрее, чем доступ к файлу через стандартные файловые операции, такие как чтение и запись. Поскольку работа с сопоставленной памятью осуществляется напрямую, некоторые интересные решения могут быть построены с помощью атомарных операций с памятью, таких как операции сравнения и установки, что позволяет использовать очень эффективные каналы связи между потоками и процессами.  Поскольку не все части сопоставленной виртуальной памяти должны одновременно находиться в реальной памяти, сегмент сопоставленной памяти может быть намного больше, чем физическая оперативная память компьютера, на котором он работает. Если часть сопоставленной памяти недоступна при обращении к ней, операционная система временно приостанавливает текущий поток и загружает отсутствующую страницу, после чего работа может возобновиться снова. Другие преимущества сопоставленных файлов заключаются в том, они могут быть совместно использоваться процессами, запущенными в разных JVM, а также в том, что файлы остаются постоянными и могут быть просмотрены  с помощью любого инструмента для работы с файлами, например hexdump. Новая функция Foreign Function and Memory, которая во второй раз появляется ​​в Java 20, позволяет сопоставлять большие сегменты памяти с файлом. Вот как можно создать сегмент памяти размером 4 ГБ, сопоставленный с файлом. Разреженный файл — это файл, в котором информация может храниться эффективным образом, если фактически не все части файла фактически используются. Файл с большими неиспользуемыми «дырами» является примером такого файла, в котором только фактически используемые секции хранятся в основном физическом файле. В действительности, однако, неиспользуемые дыры также потребляют некоторое количество ресурсов, хотя и гораздо меньше, чем их используемые аналоги. Пока разреженный файл не заполнен слишком большим количеством данных, можно выделить разреженный файл, размер которого намного больше доступного физического дискового пространства. Например, можно выделить пустой сегмент памяти объемом 10 ТБ, сопоставленный с разреженным файлом, в файловой системе с очень малой доступной емкостью. Следует отметить, что не все платформы поддерживают разреженные файлы. Вот пример того, как создать и получить доступ к содержимому файла через сегмент памяти с разреженным содержимым. Например, автоматически расширять реальные основные данные в файле по мере необходимости: Примечание. Будет казаться, что файл состоит из 4 Гб данных, но на самом деле файл вообще не использует никакого (видимого) пространства файловой системы: Реализация разреженных файлов различается на многих платформах, поддерживаемых Java, и, следовательно, различные свойства разреженных файлов будут зависеть от того, где развернуто приложение.  Я использую Mac M1 под управлением macOS Monteray (12.6.1) с 32 Гб оперативной памяти и 1 Тб дисковой памяти (из которых доступно 900 Гб). Мне удалось отобразить один разреженный файл размером до 64 Тбайт, используя один сопоставленный сегмент памяти на моей машине (используя стандартные настройки): Можно увеличить объем сопоставленной памяти, но это выходит за рамки данной статьи. В реальных приложениях лучше отображать в память меньшие части разреженного файла, чем отображать весь разреженный файл в одном фрагменте. Эти меньшие сопоставления затем будут служить «окнами» в большой базовый файл.  Во всяком случае, он выглядит довольно огромным: Создание пустого разреженного файла размером 64 Тб заняло на моей машине около 200 мс. Как видно из вышеизложенного, можно получить доступ к одной и той же базовой физической памяти из разных потоков (и даже из разных процессов) с помощью сопоставления файлов несмотря на то, что они просматриваются через несколько отдельных экземпляров сегмента памяти, включенных в потоки.  Попробуйте сопоставленные сегменты уже сегодня, загрузив предварительную сборку JDK: JDK 20 Early-Access Build. Не забудьте указать флаг --enable-preview JVM, иначе ваш код не запустится.