Spec-Zone.ru › OpenJDK 24

Интерфейс 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.

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

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

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

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

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

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

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

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

C момента:
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 Virtual Machine. Например, "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 Virtual Machine. Например, "java/util/List".
classBeingRedefined - если это вызвано переопределением или повторным преобразованием, класс, который переопределяется или повторно преобразуется; если это загрузка класса, null
protectionDomain - область защиты класса, который определён или переопределён
classfileBuffer - входной буфер байтов в формате файла класса — не должен быть изменён
Возвращает:
буфер хорошо сформированного файла класса (результат преобразования) или null, если преобразование не выполняется
Выбрасывает:
IllegalClassFormatException - если вход не представляет собой хорошо сформированный файл класса
С тех пор:
9

© 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://download.java.net/java/early_access/jdk24/docs/api/java.instrument/java/lang/instrument/ClassFileTransformer.html

Spec-Zone.ru

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