MemorySegment и Arena
Выделяйте память вне кучи
«MemorySegment и Arena» — бесплатный урок Java Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.
Память вне кучи
FFM представляет нативную память вне кучи с помощью двух основных типов: MemorySegment обозначает непрерывную область памяти, а Arena управляет её временем жизни.
Вместе они заменяют небезопасное ручное управление буферами, применявшееся раньше.
Что такое MemorySegment
MemorySegment — это типизированное представление блока памяти. Оно знает свой размер и своё время жизни, а каждый доступ к нему проверяется на выход за границы.
Сегменты могут находиться вне кучи (в нативной памяти) или оборачивать массив в куче.
Что такое Arena
Arena выделяет сегменты и определяет, когда они освобождаются. После закрытия Arena все её сегменты становятся недействительными за один детерминированный шаг.
Arena.ofConfined(): один поток, явное закрытиеArena.ofShared(): доступ из нескольких потоковArena.global(): никогда не освобождаетсяArena.ofAuto(): освобождается сборщиком мусора
Выделение сегмента
Типичный шаблон — использовать изолированную Arena в конструкции try-with-resources. Выделите байты, используйте их, а при закрытии всё будет освобождено.
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment seg = arena.allocate(16);
System.out.println("Allocated bytes: " + seg.byteSize());
}
System.out.println("Arena closed, memory freed");
}
}Запись и чтение
Чтение и запись выполняются через типизированные средства доступа, которым передаются ValueLayout и смещение. Это обеспечивает типобезопасный и выровненный доступ.
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment seg = arena.allocate(ValueLayout.JAVA_INT);
seg.set(ValueLayout.JAVA_INT, 0, 42);
int value = seg.get(ValueLayout.JAVA_INT, 0);
System.out.println("Stored and read: " + value);
}
}
}Выделение типизированных ячеек
Вместо указания необработанного количества байтов выделяйте память по разметке. arena.allocate(JAVA_INT) резервирует ровно столько правильно выровненных байтов, сколько требуется для одного значения типа int.
Это избавляет от ручных вычислений размера.
Массивы значений
Чтобы хранить несколько элементов, выделите память под разметку последовательности или передайте количество элементов. При индексном доступе используется смещение, вычисленное на основе размера элемента.
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment ints = arena.allocate(ValueLayout.JAVA_INT, 5);
for (int i = 0; i < 5; i++) {
ints.setAtIndex(ValueLayout.JAVA_INT, i, i * 10);
}
System.out.println("Element 3: " + ints.getAtIndex(ValueLayout.JAVA_INT, 3));
}
}
}Проверка границ
Чтение или запись за пределами сегмента приводит к исключению IndexOutOfBoundsException. Доступ к сегменту после закрытия его Arena приводит к исключению IllegalStateException.
Именно эти проверки делают память FFM безопасной, в отличие от JNI.
Изоляция
Изолированная Arena связывает свои сегменты с потоком, который их создал. При доступе к ним из другого потока возникает исключение WrongThreadException.
Для действительно общей памяти используйте Arena.ofShared(), разрешающую доступ из нескольких потоков с небольшими дополнительными затратами.
Работа со строками
FFM предоставляет вспомогательные средства для преобразования строк Java и строк C. allocateUtf8String (в более новых версиях: allocateFrom) записывает строку, завершающуюся нулевым байтом, а getUtf8String считывает такую строку.
import java.lang.foreign.*;
public class Main {
public static void main(String[] args) {
try (Arena arena = Arena.ofConfined()) {
MemorySegment cString = arena.allocateUtf8String("hello");
System.out.println("Read back: " + cString.getUtf8String(0));
}
}
}Выбор Arena
Рекомендации:
- Краткоживущие буферы для одного потока:
ofConfined() - Общие буферы для нескольких потоков:
ofShared() - Время жизни управляется сборщиком мусора:
ofAuto() - Константы, общие для всего процесса:
global()
Быстрая проверка
Вспомните, что определяет момент освобождения нативной памяти.
Итоги
Вы узнали, как управлять памятью вне кучи:
MemorySegment: область памяти с проверкой границArena: управляет временем жизни (изолированным, общим, автоматическим или глобальным)- Типизированный доступ через
ValueLayoutс помощьюget/setиgetAtIndex - Безопасность благодаря проверке границ и изоляции
Далее: вызов нативных функций с помощью дескрипторов вызова вниз.
Часто задаваемые вопросы
Урок «MemorySegment и Arena» бесплатный?
Да — полный текст урока «MemorySegment и Arena» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.
Чему я научусь в уроке «MemorySegment и Arena»?
Выделяйте память вне кучи Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Java Academy?
Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «MemorySegment и Arena»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Java Academy?
Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Почему FFM лучше JNI
- MemorySegment и Arena
- Дескрипторы вызовов downcall
- Макеты и структуры