Интерфейс 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, это облегчает ведение журнала или отладку ошибок формата.

Обратите внимание, что термин файл класса используется в соответствии с определением в разделе 3.1 спецификации The Java™ Virtual Machine Specification, обозначая последовательность байтов в формате файла класса, независимо от того, находятся ли они в файле или нет.

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

© 1993, 2020, 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/11/docs/api/java.instrument/java/lang/instrument/ClassFileTransformer.html

Spec-Zone .ru
спецификации, руководства, описания, API