Java Academy · Урок

Макеты и структуры

Описывайте макеты нативной памяти

Урок 4 из 413 шагов

«Макеты и структуры» — бесплатный урок Java Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Описание нативной памяти

Нативные данные редко представлены одним значением. В C используются структуры, массивы и объединения. FFM моделирует эти формы с помощью разметок памяти, позволяя безопасно читать и записывать структурированные нативные данные.

Семейство разметок

Типы разметок образуют небольшую иерархию:

  • ValueLayout: примитивное значение (целое число, длинное целое число, число двойной точности, адрес)
  • SequenceLayout: массив фиксированного размера из элементов одной разметки
  • StructLayout: поля, расположенные последовательно
  • UnionLayout: перекрывающиеся поля

Разметка значения

Самые простые разметки — встроенные разметки значений. Они содержат сведения о размере, выравнивании и порядке байтов.

import java.lang.foreign.ValueLayout;

public class Main {
    public static void main(String[] args) {
        System.out.println("int size: " + ValueLayout.JAVA_INT.byteSize());
        System.out.println("double size: " + ValueLayout.JAVA_DOUBLE.byteSize());
    }
}

Определение структуры

Смоделируйте структуру C с помощью MemoryLayout.structLayout(...), задав имя каждого поля с помощью withName. Рассмотрим структуру C struct Point { int x; int y; }.

import java.lang.foreign.*;

public class Main {
    public static void main(String[] args) {
        StructLayout point = MemoryLayout.structLayout(
            ValueLayout.JAVA_INT.withName("x"),
            ValueLayout.JAVA_INT.withName("y"));
        System.out.println("Point size: " + point.byteSize());
    }
}

Дескрипторы VarHandle для полей

Чтобы прочитать или записать именованное поле, получите VarHandle с помощью выражения пути. groupElement("x") выбирает поле по имени.

import java.lang.foreign.*;
import java.lang.invoke.VarHandle;

public class Main {
    public static void main(String[] args) {
        StructLayout point = MemoryLayout.structLayout(
            ValueLayout.JAVA_INT.withName("x"),
            ValueLayout.JAVA_INT.withName("y"));
        VarHandle xHandle = point.varHandle(
            MemoryLayout.PathElement.groupElement("x"));
        System.out.println("Built VarHandle for x: " + xHandle);
    }
}

Чтение и запись структуры

Выделите сегмент размером, соответствующим разметке, а затем с помощью дескрипторов переменных задайте и получите значения полей. Это аналогично заполнению структуры C.

import java.lang.foreign.*;
import java.lang.invoke.VarHandle;

public class Main {
    public static void main(String[] args) {
        StructLayout point = MemoryLayout.structLayout(
            ValueLayout.JAVA_INT.withName("x"),
            ValueLayout.JAVA_INT.withName("y"));
        VarHandle xh = point.varHandle(MemoryLayout.PathElement.groupElement("x"));
        VarHandle yh = point.varHandle(MemoryLayout.PathElement.groupElement("y"));
        try (Arena arena = Arena.ofConfined()) {
            MemorySegment p = arena.allocate(point);
            xh.set(p, 0L, 3);
            yh.set(p, 0L, 4);
            System.out.println("Point = (" + xh.get(p, 0L) + ", " + yh.get(p, 0L) + ")");
        }
    }
}

Заполнение и выравнивание

Компиляторы C вставляют заполнение, чтобы поля были выровнены. FFM не добавляет его автоматически, поэтому для точного соответствия разметке C необходимо включить MemoryLayout.paddingLayout(n).

Неправильное выравнивание повредит все поля после промежутка.

Пример явного заполнения

В структуре struct { char c; int n; } значение типа int должно быть выровнено по границе 4 байт, поэтому после значения char следуют 3 байта заполнения.

import java.lang.foreign.*;

public class Main {
    public static void main(String[] args) {
        StructLayout s = MemoryLayout.structLayout(
            ValueLayout.JAVA_BYTE.withName("c"),
            MemoryLayout.paddingLayout(3),
            ValueLayout.JAVA_INT.withName("n"));
        System.out.println("Aligned struct size: " + s.byteSize());
    }
}

Разметки последовательностей

SequenceLayout описывает массив. MemoryLayout.sequenceLayout(count, element) моделирует, например, массив из 10 чисел двойной точности.

import java.lang.foreign.*;

public class Main {
    public static void main(String[] args) {
        SequenceLayout arr = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_DOUBLE);
        System.out.println("Array bytes: " + arr.byteSize());
    }
}

Вложенные разметки

Разметки можно объединять. Структура может содержать последовательность, а последовательность — структуры. Такие выражения пути, как sequenceElement() и groupElement(name), позволяют переходить к данным на любом уровне вложенности.

Это позволяет работать с реальными структурами данных C любой сложности.

Смещения и выделение срезов

С помощью пути можно получить byteOffset поля, а затем использовать segment.asSlice(offset, size), чтобы получить дочерний сегмент. Это удобно, когда нужно передать нативной функции одно поле структуры.

Быстрая проверка

Вспомните распространённую проблему со структурами.

Итоги

Вы научились описывать нативные данные:

  • Семейство разметок: ValueLayout, SequenceLayout, StructLayout, UnionLayout
  • Задавайте имена полям с помощью withName, а доступ осуществляйте через VarHandle и элементы пути
  • Добавляйте явное paddingLayout для правильного выравнивания
  • Объединяйте вложенные разметки и создавайте срезы с помощью asSlice

На этом курс по API внешних функций и памяти завершён.

Можно начать бесплатно

Изучай Java с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
104
Уроки
374

Часто задаваемые вопросы

Урок «Макеты и структуры» бесплатный?

Да — полный текст урока «Макеты и структуры» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Макеты и структуры»?

Описывайте макеты нативной памяти Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Макеты и структуры»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Почему FFM лучше JNI
  2. MemorySegment и Arena
  3. Дескрипторы вызовов downcall
  4. Макеты и структуры
← Назад к Java Academy