Learn · concepts

Что такое ASM (Java Bytecode)? Объяснение библиотеки

ASM — это Java-библиотека для чтения и записи байт-кода JVM во время выполнения. Вот что она делает, как она работает и почему моды для Minecraft зависят от неё.

TRtrolPublished 4 min read

Что такое ASM в моддинге Minecraft?

ASM — это Java-библиотека для чтения, изменения и записи байт-кода JVM. Она работает с скомпилированными файлами .class вместо исходного кода, поэтому может проверять или переписывать класс без перекомпиляции. Моды для Minecraft используют её, потому что она позволяет патчить игру во время загрузки, после того как игра уже скомпилирована.

Почему существует патчинг байт-кода

Игра Minecraft поставляется в виде скомпилированного байт-кода, а не исходного кода. Это означает, что автор мода не может изменить исходный код и перекомпилировать всю игру: исходный код отсутствует. Единственный способ патчить код, которым вы не владеете, — это вмешаться на уровне байт-кода, наборе инструкций, которые фактически выполняет Java Virtual Machine. ASM — это практичный инструмент для этой задачи.

Как работает ASM

ASM преобразует скомпилированный класс в нечто, что может редактировать программа. Файл .class — это просто байт-код, инструкции, которые выполняет Java Virtual Machine. ASM разбирает этот байт-код, предоставляет вам методы и поля и позволяет добавлять, удалять или изменять инструкции. Затем он записывает новый допустимый класс.

Обычный Java не может сделать это самостоятельно. Компилятор преобразует ваш исходный код в байт-код один раз, и после этого байт-код фиксируется. ASM вмешивается на уровне байт-кода, который является уровнем ниже исходного кода, который вы обычно пишете.

Паттерн "посетитель" и API на основе деревьев

ASM читает класс с помощью ClassReader и записывает его с помощью ClassWriter. Между этими двумя этапами ваш код обходит части класса и решает, что изменить. Существует два подхода:

Подход с посетителем проходит по классу по одному элементу за раз. Он быстрый и использует мало памяти, поскольку никогда не хранит весь класс целиком. Древовидный подход загружает класс в объекты, по которым можно свободно перемещаться и редактировать, что упрощает рассуждения о более крупных изменениях, но использует больше памяти.

ПодходКак работаетЛучше всего подходит для
API посетителяПотоковая передача событий класса по мере их чтенияНебольшие, быстрые изменения с низким потреблением памяти
Древовидный APIСоздает редактируемую объектную модель классаБолее крупные или сложные переписывания

Почему моды Minecraft используют ASM

Модам необходимо изменять код игры, который они не писали и не могут перекомпилировать. Игра поставляется в виде скомпилированных классов, поэтому единственный способ проникновения — на уровне байт-кода, и именно это предоставляет ASM. Мод может внедрить перехватчик в метод игры, перенаправить вызов или добавить поле, все это при запуске.

Большинство моддеров не вызывают ASM напрямую. Они используют Mixin, высокоуровневый фреймворк, который располагается поверх ASM и преобразует простые аннотации в изменения байт-кода. Вы пишете небольшой класс Java, описывающий изменение, а фреймворк выполняет низкоуровневую работу с ASM за вас. Особенно Fabric моды полагаются на эту цепочку.

Когда вам потребуется прямой доступ к ASM

Редко когда автор мода пишет "сырой" ASM напрямую. Это проявляется, когда инструменту требуется больший контроль, чем может выразить аннотация, например, загрузчику, обфускатору или патчеру, который целиком переписывает классы. Для обычных модов слоя аннотаций вполне достаточно, и он гораздо менее подвержен ошибкам.

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