Spec-Zone.ru › OpenJDK 25

Интерфейс ClassFileTransformer

public interface ClassFileTransformer
Преобразователь файлов классов. Агент регистрирует реализацию этого интерфейса с помощью метода addTransformer, чтобы метод преобразователя transform вызывался при загрузке классов, их redefined или retransformed. Реализация должна переопределять один из определённых здесь методов transform. Преобразователи вызываются до того, как класс будет определён виртуальной машиной Java.

Существует два вида преобразователей, которые определяются параметром canRetransform метода Instrumentation.addTransformer(ClassFileTransformer,boolean):

  • способные к повторному преобразованию преобразователи, добавленные с параметром canRetransform, равным true
  • неспособные к повторному преобразованию преобразователи, добавленные с параметром canRetransform, равным false, или добавленные с помощью метода Instrumentation.addTransformer(ClassFileTransformer)

После регистрации преобразователя с помощью метода addTransformer он будет вызываться для каждого нового определения класса и каждого переопределения класса. Преобразователи, способные к повторному преобразованию, также будут вызываться при каждом повторном преобразовании класса. Запрос на новое определение класса выполняется с помощью метода ClassLoader.defineClass или его нативных эквивалентов. Запрос на переопределение класса выполняется с помощью метода Instrumentation.redefineClasses или его нативных эквивалентов. Запрос на повторное преобразование класса выполняется с помощью метода Instrumentation.retransformClasses или его нативных эквивалентов. Преобразователь вызывается во время обработки запроса, до проверки или применения байтов файла класса. Если преобразователей несколько, преобразования объединяются в цепочку вызовов transform. То есть байтовый массив, возвращённый одним вызовом transform, становится входными данными (через параметр classfileBuffer) для следующего вызова.

Преобразования применяются в следующем порядке:

  • Преобразователи, неспособные к повторному преобразованию
  • Нативные преобразователи, неспособные к повторному преобразованию
  • Преобразователи, способные к повторному преобразованию
  • Нативные преобразователи, способные к повторному преобразованию

При повторном преобразовании преобразователи, неспособные к повторному преобразованию, не вызываются; вместо этого повторно используется результат предыдущего преобразования. Во всех остальных случаях вызывается этот метод. В каждой из этих групп преобразователи вызываются в порядке регистрации. Нативные преобразователи предоставляются событием ClassFileLoadHook в интерфейсе Java Virtual Machine Tool Interface.

Входные данные (через параметр classfileBuffer) для первого преобразователя:

  • при новом определении класса — байты, переданные в ClassLoader.defineClass
  • при переопределении класса — definitions.getDefinitionClassFile(), где definitions — параметр метода Instrumentation.redefineClasses
  • при повторном преобразовании класса — байты, переданные при новом определении класса или, если класс переопределялся, при последнем переопределении; все преобразования, выполненные преобразователями, неспособными к повторному преобразованию, автоматически применяются повторно без изменений; подробности см. в описании метода Instrumentation.retransformClasses

Если реализующий метод определяет, что преобразования не требуются, он должен вернуть null. В противном случае он должен создать новый массив byte[], скопировать в него входные данные classfileBuffer и все требуемые преобразования, а затем вернуть новый массив. Входные данные classfileBuffer изменять нельзя.

В случаях повторного преобразования и переопределения преобразователь должен поддерживать семантику переопределения: если класс, изменённый преобразователем при первоначальном определении, впоследствии повторно преобразуется или переопределяется, преобразователь должен гарантировать, что второй выходной файл класса является допустимым переопределением первого выходного файла класса.

Если преобразователь выбрасывает исключение (которое он не перехватывает), последующие преобразователи всё равно будут вызваны, а загрузка, переопределение или повторное преобразование всё равно будут предприняты. Таким образом, выбрасывание исключения имеет тот же эффект, что и возврат null. Чтобы предотвратить непредвиденное поведение при возникновении непроверяемых исключений в коде преобразователя, преобразователь может перехватывать Throwable. Если преобразователь считает, что classFileBuffer не является корректно сформированным файлом класса, ему следует выбросить IllegalClassFormatException; хотя это имеет тот же эффект, что и возврат null, такой подход упрощает регистрацию ошибок или отладку повреждений формата.

Обратите внимание, что термин файл класса используется в значении, определённом в главе 4 «Формат файла class» из документа Спецификация виртуальной машины Java, и означает последовательность байтов в формате файла класса независимо от того, хранятся ли они в файле.

Примечание API:
При преобразовании основных классов JDK, которые одновременно требуются в процессе преобразования, необходимо проявлять особую осторожность, поскольку это может привести к циклической зависимости классов или ошибкам связывания.

Например, если при вызове метода transform() для класса C требуется загрузить или разрешить тот же класс C, будет выброшена ошибка, являющаяся экземпляром LinkageError (или его подкласса). Если LinkageError возникает во время разрешения ссылки (см. раздел 5.4.3 «Разрешение» документа Спецификация виртуальной машины Java) для класса D, разрешение соответствующей ссылки в классе D при любой последующей попытке навсегда завершится той же ошибкой. Это означает, что LinkageError, возникшая при преобразовании C в классе D, напрямую не связанном с C, может впоследствии повторно возникать в произвольном пользовательском коде, использующем D.

Начиная с:
1.5
См. также:
  • Instrumentation

Краткое описание методов

Модификатор и тип Метод Описание
default byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
Преобразует указанный файл класса и возвращает новый файл класса для замены.
default byte[] transform(Module module, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
Преобразует указанный файл класса и возвращает новый файл класса для замены.

Подробное описание методов

transform

default byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
Преобразует указанный файл класса и возвращает новый файл класса для замены. Этот метод вызывается, если метод Module, принимающий transform, не переопределён.
Требования к реализации:
Реализация по умолчанию возвращает null.
Параметры:
loader — загрузчик, определяющий преобразуемый класс; может иметь значение null, если это загрузчик начального уровня
className — имя класса во внутреннем формате полностью квалифицированных имён классов и интерфейсов, определённом в Спецификации виртуальной машины Java. Например, "java/util/List".
classBeingRedefined — если вызов вызван переопределением или повторным преобразованием, переопределяемый или повторно преобразуемый класс; если это загрузка класса, null
protectionDomain — домен защиты определяемого или переопределяемого класса
classfileBuffer — входной байтовый буфер в формате файла класса; изменять нельзя
Возвращает:
корректно сформированный буфер файла класса (результат преобразования) или null, если преобразование не выполняется
Выбрасывает:
IllegalClassFormatException — если входные данные не являются корректно сформированным файлом класса

transform

default byte[] transform(Module module, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
Преобразует указанный файл класса и возвращает новый файл класса для замены.
Требования к реализации:
Реализация этого метода по умолчанию вызывает метод transform.
Параметры:
module — модуль преобразуемого класса
loader — загрузчик, определяющий преобразуемый класс; может иметь значение null, если это загрузчик начального уровня
className — имя класса во внутреннем формате полностью квалифицированных имён классов и интерфейсов, определённом в Спецификации виртуальной машины Java. Например, "java/util/List".
classBeingRedefined — если вызов вызван переопределением или повторным преобразованием, переопределяемый или повторно преобразуемый класс; если это загрузка класса, null
protectionDomain — домен защиты определяемого или переопределяемого класса
classfileBuffer — входной байтовый буфер в формате файла класса; изменять нельзя
Возвращает:
корректно сформированный буфер файла класса (результат преобразования) или null, если преобразование не выполняется
Выбрасывает:
IllegalClassFormatException — если входные данные не являются корректно сформированным файлом класса
Начиная с:
9

Сообщить об ошибке или предложить улучшение
Дополнительные справочные материалы по API и документацию для разработчиков см. в разделе Документация Java SE, содержащем более подробные описания для разработчиков, концептуальные обзоры, определения терминов, обходные решения и примеры работающего кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или её аффилированных лиц в США и других странах.
Авторские права © 1993, 2025, Oracle и/или её аффилированные лица, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/25/docs/api/java.instrument/java/lang/instrument/ClassFileTransformer.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API