| /* | |
| * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package java.lang.instrument; | |
| import java.security.ProtectionDomain; | |
| /* | |
| * Copyright 2003 Wily Technology, Inc. | |
| */ | |
| /** | |
| * A transformer of class files. An agent registers an implementation of this | |
| * interface using the {@link Instrumentation#addTransformer addTransformer} | |
| * method so that the transformer's {@link | |
| * ClassFileTransformer#transform(Module,ClassLoader,String,Class,ProtectionDomain,byte[]) | |
| * transform} method is invoked when classes are loaded, | |
| * {@link Instrumentation#redefineClasses redefined}, or | |
| * {@link Instrumentation#retransformClasses retransformed}. The implementation | |
| * should override one of the {@code transform} methods defined here. | |
| * Transformers are invoked before the class is defined by the Java virtual | |
| * machine. | |
| * | |
| * <P> | |
| * There are two kinds of transformers, determined by the <code>canRetransform</code> | |
| * parameter of | |
| * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean)}: | |
| * <ul> | |
| * <li><i>retransformation capable</i> transformers that were added with | |
| * <code>canRetransform</code> as true | |
| * </li> | |
| * <li><i>retransformation incapable</i> transformers that were added with | |
| * <code>canRetransform</code> as false or where added with | |
| * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer)} | |
| * </li> | |
| * </ul> | |
| * | |
| * <P> | |
| * Once a transformer has been registered with | |
| * {@link java.lang.instrument.Instrumentation#addTransformer(ClassFileTransformer,boolean) | |
| * addTransformer}, | |
| * the transformer will be called for every new class definition and every class redefinition. | |
| * Retransformation capable transformers will also be called on every class retransformation. | |
| * The request for a new class definition is made with | |
| * {@link java.lang.ClassLoader#defineClass ClassLoader.defineClass} | |
| * or its native equivalents. | |
| * The request for a class redefinition is made with | |
| * {@link java.lang.instrument.Instrumentation#redefineClasses Instrumentation.redefineClasses} | |
| * or its native equivalents. | |
| * The request for a class retransformation is made with | |
| * {@link java.lang.instrument.Instrumentation#retransformClasses Instrumentation.retransformClasses} | |
| * or its native equivalents. | |
| * The transformer is called during the processing of the request, before the class file bytes | |
| * have been verified or applied. | |
| * When there are multiple transformers, transformations are composed by chaining the | |
| * <code>transform</code> calls. | |
| * That is, the byte array returned by one call to <code>transform</code> becomes the input | |
| * (via the <code>classfileBuffer</code> parameter) to the next call. | |
| * | |
| * <P> | |
| * Transformations are applied in the following order: | |
| * <ul> | |
| * <li>Retransformation incapable transformers | |
| * </li> | |
| * <li>Retransformation incapable native transformers | |
| * </li> | |
| * <li>Retransformation capable transformers | |
| * </li> | |
| * <li>Retransformation capable native transformers | |
| * </li> | |
| * </ul> | |
| * | |
| * <P> | |
| * For retransformations, the retransformation incapable transformers are not | |
| * called, instead the result of the previous transformation is reused. | |
| * In all other cases, this method is called. | |
| * Within each of these groupings, transformers are called in the order registered. | |
| * Native transformers are provided by the <code>ClassFileLoadHook</code> event | |
| * in the Java Virtual Machine Tool Interface). | |
| * | |
| * <P> | |
| * The input (via the <code>classfileBuffer</code> parameter) to the first | |
| * transformer is: | |
| * <ul> | |
| * <li>for new class definition, | |
| * the bytes passed to <code>ClassLoader.defineClass</code> | |
| * </li> | |
| * <li>for class redefinition, | |
| * <code>definitions.getDefinitionClassFile()</code> where | |
| * <code>definitions</code> is the parameter to | |
| * {@link java.lang.instrument.Instrumentation#redefineClasses | |
| * Instrumentation.redefineClasses} | |
| * </li> | |
| * <li>for class retransformation, | |
| * the bytes passed to the new class definition or, if redefined, | |
| * the last redefinition, with all transformations made by retransformation | |
| * incapable transformers reapplied automatically and unaltered; | |
| * for details see | |
| * {@link java.lang.instrument.Instrumentation#retransformClasses | |
| * Instrumentation.retransformClasses} | |
| * </li> | |
| * </ul> | |
| * | |
| * <P> | |
| * If the implementing method determines that no transformations are needed, | |
| * it should return <code>null</code>. | |
| * Otherwise, it should create a new <code>byte[]</code> array, | |
| * copy the input <code>classfileBuffer</code> into it, | |
| * along with all desired transformations, and return the new array. | |
| * The input <code>classfileBuffer</code> must not be modified. | |
| * | |
| * <P> | |
| * In the retransform and redefine cases, | |
| * the transformer must support the redefinition semantics: | |
| * if a class that the transformer changed during initial definition is later | |
| * retransformed or redefined, the | |
| * transformer must insure that the second class output class file is a legal | |
| * redefinition of the first output class file. | |
| * | |
| * <P> | |
| * If the transformer throws an exception (which it doesn't catch), | |
| * subsequent transformers will still be called and the load, redefine | |
| * or retransform will still be attempted. | |
| * Thus, throwing an exception has the same effect as returning <code>null</code>. | |
| * To prevent unexpected behavior when unchecked exceptions are generated | |
| * in transformer code, a transformer can catch <code>Throwable</code>. | |
| * If the transformer believes the <code>classFileBuffer</code> does not | |
| * represent a validly formatted class file, it should throw | |
| * an <code>IllegalClassFormatException</code>; | |
| * while this has the same effect as returning null. it facilitates the | |
| * logging or debugging of format corruptions. | |
| * | |
| * <P> | |
| * Note the term <i>class file</i> is used as defined in chapter {@jvms 4} The | |
| * {@code class} File Format of <cite>The Java Virtual Machine Specification</cite>, | |
| * to mean a sequence of bytes in class file format, whether or not they reside in a | |
| * file. | |
| * | |
| * @apiNote | |
| * Great care must be taken when transforming core JDK classes which are at the | |
| * same time required during the transformation process as this can lead to class | |
| * circularity or linkage errors. | |
| * | |
| * <P> | |
| * If for example the invocation of {@link #transform transform()} for a class | |
| * {@code C} requires loading or resolving the same class {@code C}, | |
| * an error is thrown that is an instance of {@link LinkageError} (or a subclass). | |
| * If the {@link LinkageError} occurs during reference resolution (see section | |
| * {@jvms 5.4.3} Resolution of <cite>The Java Virtual Machine Specification</cite>) | |
| * for a class {@code D}, the resolution of the corresponding reference in class | |
| * {@code D} will permanently fail with the same error at any subsequent attempt. | |
| * This means that a {@link LinkageError} triggered during transformation of | |
| * {@code C} in a class {@code D} not directly related to {@code C} can repeatedly | |
| * occur later in arbitrary user code which uses {@code D}. | |
| * | |
| * @see java.lang.instrument.Instrumentation | |
| * @since 1.5 | |
| */ | |
| public interface ClassFileTransformer { | |
| /** | |
| * Transforms the given class file and returns a new replacement class file. | |
| * This method is invoked when the {@link Module Module} bearing {@link | |
| * ClassFileTransformer#transform(Module,ClassLoader,String,Class,ProtectionDomain,byte[]) | |
| * transform} is not overridden. | |
| * | |
| * @implSpec The default implementation returns null. | |
| * | |
| * @param loader the defining loader of the class to be transformed, | |
| * may be {@code null} if the bootstrap loader | |
| * @param className the name of the class in the internal form of fully | |
| * qualified class and interface names as defined in | |
| * <i>The Java Virtual Machine Specification</i>. | |
| * For example, <code>"java/util/List"</code>. | |
| * @param classBeingRedefined if this is triggered by a redefine or retransform, | |
| * the class being redefined or retransformed; | |
| * if this is a class load, {@code null} | |
| * @param protectionDomain the protection domain of the class being defined or redefined | |
| * @param classfileBuffer the input byte buffer in class file format - must not be modified | |
| * | |
| * @throws IllegalClassFormatException | |
| * if the input does not represent a well-formed class file | |
| * @return a well-formed class file buffer (the result of the transform), | |
| * or {@code null} if no transform is performed | |
| */ | |
| default byte[] | |
| transform( ClassLoader loader, | |
| String className, | |
| Class<?> classBeingRedefined, | |
| ProtectionDomain protectionDomain, | |
| byte[] classfileBuffer) | |
| throws IllegalClassFormatException { | |
| return null; | |
| } | |
| /** | |
| * Transforms the given class file and returns a new replacement class file. | |
| * | |
| * @implSpec The default implementation of this method invokes the | |
| * {@link #transform(ClassLoader,String,Class,ProtectionDomain,byte[]) transform} | |
| * method. | |
| * | |
| * @param module the module of the class to be transformed | |
| * @param loader the defining loader of the class to be transformed, | |
| * may be {@code null} if the bootstrap loader | |
| * @param className the name of the class in the internal form of fully | |
| * qualified class and interface names as defined in | |
| * <i>The Java Virtual Machine Specification</i>. | |
| * For example, <code>"java/util/List"</code>. | |
| * @param classBeingRedefined if this is triggered by a redefine or retransform, | |
| * the class being redefined or retransformed; | |
| * if this is a class load, {@code null} | |
| * @param protectionDomain the protection domain of the class being defined or redefined | |
| * @param classfileBuffer the input byte buffer in class file format - must not be modified | |
| * | |
| * @throws IllegalClassFormatException | |
| * if the input does not represent a well-formed class file | |
| * @return a well-formed class file buffer (the result of the transform), | |
| * or {@code null} if no transform is performed | |
| * | |
| * @since 9 | |
| */ | |
| default byte[] | |
| transform( Module module, | |
| ClassLoader loader, | |
| String className, | |
| Class<?> classBeingRedefined, | |
| ProtectionDomain protectionDomain, | |
| byte[] classfileBuffer) | |
| throws IllegalClassFormatException { | |
| // invoke the legacy transform method | |
| return transform(loader, | |
| className, | |
| classBeingRedefined, | |
| protectionDomain, | |
| classfileBuffer); | |
| } | |
| } |