Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
Byte Buddy is a Java library for creating Java classes at run time.
This artifact is a build of Byte Buddy with a remaining dependency onto ASM.
You should never depend on this module without repackaging Byte Buddy and ASM into your own namespace.
/*
* Copyright 2014 - Present Rafael Winterhalter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.bytebuddy.dynamic;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.build.AccessControllerPlugin;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.utility.JavaModule;
import net.bytebuddy.utility.JavaType;
import net.bytebuddy.utility.StreamDrainer;
import net.bytebuddy.utility.dispatcher.JavaDispatcher;
import net.bytebuddy.utility.nullability.AlwaysNull;
import net.bytebuddy.utility.nullability.MaybeNull;
import java.io.*;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static net.bytebuddy.matcher.ElementMatchers.isChildOf;
/**
* Locates a class file or its byte array representation when it is given its type description.
*/
public interface ClassFileLocator extends Closeable {
/**
* The file extension for a Java class file.
*/
String CLASS_FILE_EXTENSION = ".class";
/**
* The prefix folder for {@code META-INF/versions/} which contains multi-release files.
*/
String META_INF_VERSIONS = "META-INF/versions/";
/**
* Locates the class file for a given type and returns the binary data of the class file.
*
* @param name The name of the type to locate a class file representation for.
* @return Any binary representation of the type which might be illegal.
* @throws java.io.IOException If reading a class file causes an error.
*/
Resolution locate(String name) throws IOException;
/**
* Represents a class file as binary data.
*/
interface Resolution {
/**
* Checks if this binary representation is valid.
*
* @return {@code true} if this binary representation is valid.
*/
boolean isResolved();
/**
* Finds the data of this binary representation. Calling this method is only legal for resolved instances.
* For non-resolved instances, an exception is thrown.
*
* @return The requested binary data. The returned array must not be altered.
*/
byte[] resolve();
/**
* A canonical representation of an illegal binary representation.
*/
@HashCodeAndEqualsPlugin.Enhance
class Illegal implements Resolution {
/**
* The name of the unresolved class file.
*/
private final String typeName;
/**
* Creates an illegal resolution for a class file.
*
* @param typeName The name of the unresolved class file.
*/
public Illegal(String typeName) {
this.typeName = typeName;
}
/**
* {@inheritDoc}
*/
public boolean isResolved() {
return false;
}
/**
* {@inheritDoc}
*/
public byte[] resolve() {
throw new IllegalStateException("Could not locate class file for " + typeName);
}
}
/**
* Represents a byte array as binary data.
*/
@HashCodeAndEqualsPlugin.Enhance
class Explicit implements Resolution {
/**
* The represented data.
*/
private final byte[] binaryRepresentation;
/**
* Creates a new explicit resolution of a given array of binary data.
*
* @param binaryRepresentation The binary data to represent. The array must not be modified.
*/
@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "The array is not modified by class contract.")
public Explicit(byte[] binaryRepresentation) {
this.binaryRepresentation = binaryRepresentation;
}
/**
* {@inheritDoc}
*/
public boolean isResolved() {
return true;
}
/**
* {@inheritDoc}
*/
@SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "The array is not modified by class contract.")
public byte[] resolve() {
return binaryRepresentation;
}
}
}
/**
* A class file locator that cannot locate any class files.
*/
enum NoOp implements ClassFileLocator {
/**
* The singleton instance.
*/
INSTANCE;
/**
* {@inheritDoc}
*/
public Resolution locate(String name) {
return new Resolution.Illegal(name);
}
/**
* {@inheritDoc}
*/
public void close() {
/* do nothing */
}
}
/**
* A class file locator that is aware of multi-release JAR file semantics.
*/
@HashCodeAndEqualsPlugin.Enhance
abstract class MultiReleaseAware implements ClassFileLocator {
/**
* The property name of a multi-release JAR file.
*/
private static final String MULTI_RELEASE_ATTRIBUTE = "Multi-Release";
/**
* Indicates that no multi-release versions exist.
*/
protected static final int[] NO_MULTI_RELEASE = new int[0];
/**
* Contains the existing multi-release jar folders that are available for the
* current JVM version in decreasing order.
*/
private final int[] version;
/**
* Creates a multi-release aware class file locator.
*
* @param version Contains the existing multi-release jar folders that are available for the
* current JVM version in decreasing order.
*/
protected MultiReleaseAware(int[] version) {
this.version = version;
}
/**
* {@inheritDoc}
*/
public Resolution locate(String name) throws IOException {
String path = name.replace('.', '/') + CLASS_FILE_EXTENSION;
for (int index = 0; index < version.length + 1; index++) {
byte[] binaryRepresentation = doLocate(index == version.length ? path : META_INF_VERSIONS + version[index] + "/" + path);
if (binaryRepresentation != null) {
return new Resolution.Explicit(binaryRepresentation);
}
}
return new Resolution.Illegal(name);
}
/**
* Resolves a possible multi-release entry, if it exists.
*
* @param path The path of the class file.
* @return The class file's binary representation or {@code null} if it does not exist.
* @throws IOException If an I/O exception occurs.
*/
@MaybeNull
protected abstract byte[] doLocate(String path) throws IOException;
}
/**
* A simple class file locator that returns class files from a selection of given types.
*/
@HashCodeAndEqualsPlugin.Enhance
class Simple implements ClassFileLocator {
/**
* The class files that are known to this class file locator mapped by their type name.
*/
private final Map classFiles;
/**
* Creates a new simple class file locator.
*
* @param classFiles The class files that are known to this class file locator mapped by their type name.
*/
public Simple(Map classFiles) {
this.classFiles = classFiles;
}
/**
* Creates a class file locator for a single known type.
*
* @param typeName The name of the type.
* @param binaryRepresentation The binary representation of the type.
* @return An appropriate class file locator.
*/
public static ClassFileLocator of(String typeName, byte[] binaryRepresentation) {
return new Simple(Collections.singletonMap(typeName, binaryRepresentation));
}
/**
* Creates a class file locator that represents all types of a dynamic type.
*
* @param dynamicType The dynamic type to represent.
* @return A class file locator representing the dynamic type's types.
*/
public static ClassFileLocator of(DynamicType dynamicType) {
return of(dynamicType.getAllTypes());
}
/**
* Creates a class file locator that represents all types of a dynamic type.
*
* @param binaryRepresentations The binary representation of all types.
* @return A class file locator representing the dynamic type's types.
*/
public static ClassFileLocator of(Map binaryRepresentations) {
Map classFiles = new HashMap();
for (Map.Entry entry : binaryRepresentations.entrySet()) {
classFiles.put(entry.getKey().getName(), entry.getValue());
}
return new Simple(classFiles);
}
/**
* Creates a class file locator of a map of resources where class files are mapped by their path and file extension.
*
* @param binaryRepresentations A map of resource names to their binary representation.
* @return A class file locator that finds class files within the map.
*/
public static ClassFileLocator ofResources(Map binaryRepresentations) {
Map classFiles = new HashMap();
for (Map.Entry entry : binaryRepresentations.entrySet()) {
if (entry.getKey().endsWith(CLASS_FILE_EXTENSION)) {
classFiles.put(entry.getKey().substring(0, entry.getKey().length() - CLASS_FILE_EXTENSION.length()).replace('/', '.'), entry.getValue());
}
}
return new Simple(classFiles);
}
/**
* {@inheritDoc}
*/
public Resolution locate(String name) {
byte[] binaryRepresentation = classFiles.get(name);
return binaryRepresentation == null ? new Resolution.Illegal(name) : new Resolution.Explicit(binaryRepresentation);
}
/**
* {@inheritDoc}
*/
public void close() {
/* do nothing */
}
}
/**
*
* A class file locator that queries a class loader for binary representations of class files.
*
*
* Important: Even when calling {@link Closeable#close()} on this class file locator, no underlying
* class loader is closed if it implements the {@link Closeable} interface as this is typically not intended.
*
*/
@HashCodeAndEqualsPlugin.Enhance
class ForClassLoader implements ClassFileLocator {
/**
* A class loader that does not define resources of its own but allows querying for resources supplied by the boot loader.
*/
private static final ClassLoader BOOT_LOADER_PROXY = doPrivileged(BootLoaderProxyCreationAction.INSTANCE);
/**
* The class loader to query.
*/
private final ClassLoader classLoader;
/**
* Creates a new class file locator for the given class loader.
*
* @param classLoader The class loader to query which must not be the bootstrap class loader, i.e. {@code null}.
*/
protected ForClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
*
* @param action The action to execute from a privileged context.
* @param The type of the action's resolved value.
* @return The action's resolved value.
*/
@AccessControllerPlugin.Enhance
private static T doPrivileged(PrivilegedAction action) {
return action.run();
}
/**
* Creates a class file locator that queries the system class loader.
*
* @return A class file locator that queries the system class loader.
*/
public static ClassFileLocator ofSystemLoader() {
return new ForClassLoader(ClassLoader.getSystemClassLoader());
}
/**
* Creates a class file locator that queries the plaform class loader or the extension class loader if the
* current VM is not at least of version 9.
*
* @return A class file locator that queries the plaform class loader or the extension class loader.
*/
public static ClassFileLocator ofPlatformLoader() {
return of(ClassLoader.getSystemClassLoader().getParent());
}
/**
* Creates a class file locator that queries the boot loader.
*
* @return A class file locator that queries the boot loader.
*/
public static ClassFileLocator ofBootLoader() {
return new ForClassLoader(BOOT_LOADER_PROXY);
}
/**
* Creates a class file locator for a given class loader.
*
* @param classLoader The class loader to be used which might be {@code null} to represent the bootstrap loader.
* @return A corresponding source locator.
*/
public static ClassFileLocator of(@MaybeNull ClassLoader classLoader) {
return new ForClassLoader(classLoader == null ? BOOT_LOADER_PROXY : classLoader);
}
/**
* Attempts to create a binary representation of a loaded type by requesting data from its
* {@link java.lang.ClassLoader}.
*
* @param type The type of interest.
* @return The binary representation of the supplied type.
*/
public static byte[] read(Class> type) {
try {
ClassLoader classLoader = type.getClassLoader();
return locate(classLoader == null ? BOOT_LOADER_PROXY : classLoader, TypeDescription.ForLoadedType.getName(type)).resolve();
} catch (IOException exception) {
throw new IllegalStateException("Cannot read class file for " + type, exception);
}
}
/**
* Attempts to create a binary representation of several loaded types by requesting
* data from their respective {@link java.lang.ClassLoader}s.
*
* @param type The types of interest.
* @return A mapping of the supplied types to their binary representation.
*/
public static Map, byte[]> read(Class>... type) {
return read(Arrays.asList(type));
}
/**
* Attempts to create a binary representation of several loaded types by requesting
* data from their respective {@link java.lang.ClassLoader}s.
*
* @param types The types of interest.
* @return A mapping of the supplied types to their binary representation.
*/
public static Map, byte[]> read(Collection extends Class>> types) {
Map, byte[]> result = new HashMap, byte[]>();
for (Class> type : types) {
result.put(type, read(type));
}
return result;
}
/**
* Attempts to create a binary representation of several loaded types by requesting
* data from their respective {@link java.lang.ClassLoader}s.
*
* @param type The types of interest.
* @return A mapping of the supplied types' names to their binary representation.
*/
public static Map readToNames(Class>... type) {
return readToNames(Arrays.asList(type));
}
/**
* Attempts to create a binary representation of several loaded types by requesting
* data from their respective {@link java.lang.ClassLoader}s.
*
* @param types The types of interest.
* @return A mapping of the supplied types' names to their binary representation.
*/
public static Map readToNames(Collection extends Class>> types) {
Map result = new HashMap();
for (Class> type : types) {
result.put(type.getName(), read(type));
}
return result;
}
/**
* {@inheritDoc}
*/
public Resolution locate(String name) throws IOException {
return locate(classLoader, name);
}
/**
* {@inheritDoc}
*/
public void close() {
/* do nothing */
}
/**
* Locates the class file for the supplied type by requesting a resource from the class loader.
*
* @param classLoader The class loader to query.
* @param name The name of the type for which to locate a class file.
* @return A resolution for the class file.
* @throws IOException If reading the class file causes an exception.
*/
protected static Resolution locate(ClassLoader classLoader, String name) throws IOException {
InputStream inputStream = classLoader.getResourceAsStream(name.replace('.', '/') + CLASS_FILE_EXTENSION);
if (inputStream != null) {
try {
return new Resolution.Explicit(StreamDrainer.DEFAULT.drain(inputStream));
} finally {
inputStream.close();
}
} else {
return new Resolution.Illegal(name);
}
}
/**
* A privileged action for creating a proxy class loader for the boot class loader.
*/
protected enum BootLoaderProxyCreationAction implements PrivilegedAction {
/**
* The singleton instance.
*/
INSTANCE;
/**
* {@inheritDoc}
*/
public ClassLoader run() {
return new URLClassLoader(new URL[0], ClassLoadingStrategy.BOOTSTRAP_LOADER);
}
}
/**
*
* A class file locator that queries a class loader for binary representations of class files.
* The class loader is only weakly referenced.
*
*
* Important: Even when calling {@link Closeable#close()} on this class file locator, no underlying
* class loader is closed if it implements the {@link Closeable} interface as this is typically not intended.
*
*/
public static class WeaklyReferenced extends WeakReference implements ClassFileLocator {
/**
* The represented class loader's hash code.
*/
private final int hashCode;
/**
* Creates a class file locator for a class loader that is weakly referenced.
*
* @param classLoader The class loader to represent.
*/
protected WeaklyReferenced(ClassLoader classLoader) {
super(classLoader);
hashCode = System.identityHashCode(classLoader);
}
/**
* Creates a class file locator for a given class loader. If the class loader is not the bootstrap
* class loader or the system class loader which cannot be collected, the class loader is only weakly
* referenced.
*
* @param classLoader The class loader to be used. If this class loader represents the bootstrap class
* loader which is represented by the {@code null} value, this system class loader
* is used instead.
* @return A corresponding source locator.
*/
public static ClassFileLocator of(@MaybeNull ClassLoader classLoader) {
return classLoader == null || classLoader == ClassLoader.getSystemClassLoader() || classLoader == ClassLoader.getSystemClassLoader().getParent() ? ForClassLoader.of(classLoader) : new WeaklyReferenced(classLoader);
}
/**
* {@inheritDoc}
*/
public Resolution locate(String name) throws IOException {
ClassLoader classLoader = get();
return classLoader == null ? new Resolution.Illegal(name) : ForClassLoader.locate(classLoader, name);
}
/**
* {@inheritDoc}
*/
public void close() {
/* do nothing */
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public boolean equals(@MaybeNull Object other) {
if (this == other) {
return true;
} else if (other == null || getClass() != other.getClass()) {
return false;
}
WeaklyReferenced weaklyReferenced = (WeaklyReferenced) other;
ClassLoader classLoader = weaklyReferenced.get();
return classLoader != null && get() == classLoader;
}
}
}
/**
*
* A class file locator that locates class files by querying a Java module's {@code getResourceAsStream} method.
*
*
* Important: Even when calling {@link Closeable#close()} on this class file locator, no underlying
* class loader is closed if it implements the {@link Closeable} interface as this is typically not intended.
*
*/
@HashCodeAndEqualsPlugin.Enhance
class ForModule implements ClassFileLocator {
/**
* An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call.
*/
private static final Object[] NO_ARGUMENT = new Object[0];
/**
* The represented Java module.
*/
private final JavaModule module;
/**
* Creates a new class file locator for a Java module.
*
* @param module The represented Java module.
*/
protected ForModule(JavaModule module) {
this.module = module;
}
/**
* Returns a class file locator that exposes all class files of the boot module layer. This class file locator is only available
* on virtual machines of version 9 or later. On earlier versions, the returned class file locator does not locate any resources.
*
* @return A class file locator that locates classes of the boot layer.
*/
@SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "Exception should always be wrapped for clarity")
public static ClassFileLocator ofBootLayer() {
try {
Map bootModules = new HashMap();
Class> layerType = Class.forName("java.lang.ModuleLayer");
Method getPackages = JavaType.MODULE.load().getMethod("getPackages");
for (Object rawModule : (Set>) layerType.getMethod("modules").invoke(layerType.getMethod("boot").invoke(null))) {
ClassFileLocator classFileLocator = ForModule.of(JavaModule.of(rawModule));
for (Object packageName : (Set>) getPackages.invoke(rawModule, NO_ARGUMENT)) {
bootModules.put((String) packageName, classFileLocator);
}
}
return new PackageDiscriminating(bootModules);
} catch (Exception exception) {
throw new IllegalStateException("Cannot process boot layer", exception);
}
}
/**
* Returns a class file locator for the provided module. If the provided module is not named, class files are located via this
* unnamed module's class loader.
*
* @param module The module to create a class file locator for.
* @return An appropriate class file locator.
*/
public static ClassFileLocator of(JavaModule module) {
return module.isNamed() ? new ForModule(module) : ForClassLoader.of(module.getClassLoader());
}
/**
* {@inheritDoc}
*/
public Resolution locate(String name) throws IOException {
return locate(module, name);
}
/**
* Creates a resolution for a Java module's class files.
*
* @param module The Java module to query.
* @param typeName The name of the type being queried.
* @return A resolution for the query.
* @throws IOException If an I/O exception was thrown.
*/
protected static Resolution locate(JavaModule module, String typeName) throws IOException {
InputStream inputStream = module.getResourceAsStream(typeName.replace('.', '/') + CLASS_FILE_EXTENSION);
if (inputStream != null) {
try {
return new Resolution.Explicit(StreamDrainer.DEFAULT.drain(inputStream));
} finally {
inputStream.close();
}
} else {
return new Resolution.Illegal(typeName);
}
}
/**
* {@inheritDoc}
*/
public void close() {
/* do nothing */
}
/**
*
* A class file locator for a Java module that only references this module weakly. If a module was garbage collected,
* this class file locator only returns unresolved resolutions.
*
*
* Important: Even when calling {@link Closeable#close()} on this class file locator, no underlying
* class loader is closed if it implements the {@link Closeable} interface as this is typically not intended.
*
*/
public static class WeaklyReferenced extends WeakReference