// Generated by delombok at Sun Feb 26 12:31:38 KST 2017 package scouter.bytebuddy.dynamic.loading; import scouter.bytebuddy.ByteBuddy; import scouter.bytebuddy.ClassFileVersion; import scouter.bytebuddy.description.modifier.Visibility; import scouter.bytebuddy.description.type.TypeDescription; import scouter.bytebuddy.dynamic.DynamicType; import scouter.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy; import scouter.bytebuddy.implementation.FixedValue; import scouter.bytebuddy.implementation.MethodCall; import scouter.bytebuddy.utility.RandomString; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.instrument.Instrumentation; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ReflectPermission; import java.net.URL; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.util.HashMap; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; /** * <p> * A class injector is capable of injecting classes into a {@link java.lang.ClassLoader} without * requiring the class loader to being able to explicitly look up these classes. * </p> * <p> * <b>Important</b>: Byte Buddy does not supply privileges when injecting code. When using a {@link SecurityManager}, * the user of this injector is responsible for providing access to non-public properties. * </p> */ public interface ClassInjector { /** * Determines the default behavior for type injections when a type is already loaded. */ boolean ALLOW_EXISTING_TYPES = false; /** * Injects the given types into the represented class loader. * * @param types The types to load via injection. * @return The loaded types that were passed as arguments. */ Map<TypeDescription, Class<?>> inject(Map<? extends TypeDescription, byte[]> types); /** * A class injector that uses reflective method calls. */ class UsingReflection implements ClassInjector { /** * The dispatcher to use for accessing a class loader via reflection. */ private static final Dispatcher.Initializable DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE); /** * The class loader into which the classes are to be injected. */ private final ClassLoader classLoader; /** * The protection domain that is used when loading classes. */ private final ProtectionDomain protectionDomain; /** * The package definer to be queried for package definitions. */ private final PackageDefinitionStrategy packageDefinitionStrategy; /** * Determines if an exception should be thrown when attempting to load a type that already exists. */ private final boolean forbidExisting; /** * Creates a new injector for the given {@link java.lang.ClassLoader} and a default {@link java.security.ProtectionDomain} and a * trivial {@link PackageDefinitionStrategy} which does not trigger an error when discovering existent classes. * * @param classLoader The {@link java.lang.ClassLoader} into which new class definitions are to be injected. Must not be the bootstrap loader. */ public UsingReflection(ClassLoader classLoader) { this(classLoader, ClassLoadingStrategy.NO_PROTECTION_DOMAIN); } /** * Creates a new injector for the given {@link java.lang.ClassLoader} and a default {@link PackageDefinitionStrategy} where the * injection of existent classes does not trigger an error. * * @param classLoader The {@link java.lang.ClassLoader} into which new class definitions are to be injected. Must not be the bootstrap loader. * @param protectionDomain The protection domain to apply during class definition. */ public UsingReflection(ClassLoader classLoader, ProtectionDomain protectionDomain) { this(classLoader, protectionDomain, PackageDefinitionStrategy.Trivial.INSTANCE, ALLOW_EXISTING_TYPES); } /** * Creates a new injector for the given {@link java.lang.ClassLoader} and {@link java.security.ProtectionDomain}. * * @param classLoader The {@link java.lang.ClassLoader} into which new class definitions are to be injected.Must not be the bootstrap loader. * @param protectionDomain The protection domain to apply during class definition. * @param packageDefinitionStrategy The package definer to be queried for package definitions. * @param forbidExisting Determines if an exception should be thrown when attempting to load a type that already exists. */ public UsingReflection(ClassLoader classLoader, ProtectionDomain protectionDomain, PackageDefinitionStrategy packageDefinitionStrategy, boolean forbidExisting) { if (classLoader == null) { throw new IllegalArgumentException("Cannot inject classes into the bootstrap class loader"); } this.classLoader = classLoader; this.protectionDomain = protectionDomain; this.packageDefinitionStrategy = packageDefinitionStrategy; this.forbidExisting = forbidExisting; } /** * Indicates if this class injection is available on the current VM. * * @return {@code true} if this class injection is available. */ public static boolean isAvailable() { return DISPATCHER.isAvailable(); } /** * Creates a class injector for the system class loader. * * @return A class injector for the system class loader. */ public static ClassInjector ofSystemClassLoader() { return new UsingReflection(ClassLoader.getSystemClassLoader()); } @Override public Map<TypeDescription, Class<?>> inject(Map<? extends TypeDescription, byte[]> types) { Dispatcher dispatcher = DISPATCHER.initialize(); Map<TypeDescription, Class<?>> loadedTypes = new HashMap<TypeDescription, Class<?>>(); for (Map.Entry<? extends TypeDescription, byte[]> entry : types.entrySet()) { String typeName = entry.getKey().getName(); synchronized (dispatcher.getClassLoadingLock(classLoader, typeName)) { Class<?> type = dispatcher.findClass(classLoader, typeName); if (type == null) { int packageIndex = typeName.lastIndexOf('.'); if (packageIndex != -1) { String packageName = typeName.substring(0, packageIndex); PackageDefinitionStrategy.Definition definition = packageDefinitionStrategy.define(classLoader, packageName, typeName); if (definition.isDefined()) { Package definedPackage = dispatcher.getPackage(classLoader, packageName); if (definedPackage == null) { dispatcher.definePackage(classLoader, packageName, definition.getSpecificationTitle(), definition.getSpecificationVersion(), definition.getSpecificationVendor(), definition.getImplementationTitle(), definition.getImplementationVersion(), definition.getImplementationVendor(), definition.getSealBase()); } else if (!definition.isCompatibleTo(definedPackage)) { throw new SecurityException("Sealing violation for package " + packageName); } } } type = dispatcher.defineClass(classLoader, typeName, entry.getValue(), protectionDomain); } else if (forbidExisting) { throw new IllegalStateException("Cannot inject already loaded type: " + type); } loadedTypes.put(entry.getKey(), type); } } return loadedTypes; } /** * A dispatcher for accessing a {@link ClassLoader} reflectively. */ protected interface Dispatcher { /** * Indicates a class that is currently not defined. */ Class<?> UNDEFINED = null; /** * Returns the lock for loading the specified class. * * @param classLoader the class loader to inject the class into. * @param name The name of the class. * @return The lock for loading this class. */ Object getClassLoadingLock(ClassLoader classLoader, String name); /** * Looks up a class from the given class loader. * * @param classLoader The class loader for which a class should be located. * @param name The binary name of the class that should be located. * @return The class for the binary name or {@code null} if no such class is defined for the provided class loader. */ Class<?> findClass(ClassLoader classLoader, String name); /** * Defines a class for the given class loader. * * @param classLoader The class loader for which a new class should be defined. * @param name The binary name of the class that should be defined. * @param binaryRepresentation The binary representation of the class. * @param protectionDomain The protection domain for the defined class. * @return The defined, loaded class. */ Class<?> defineClass(ClassLoader classLoader, String name, byte[] binaryRepresentation, ProtectionDomain protectionDomain); /** * Looks up a package from a class loader. * * @param classLoader The class loader to query. * @param name The binary name of the package. * @return The package for the given name as defined by the provided class loader or {@code null} if no such package exists. */ Package getPackage(ClassLoader classLoader, String name); /** * Defines a package for the given class loader. * * @param classLoader The class loader for which a package is to be defined. * @param name The binary name of the package. * @param specificationTitle The specification title of the package or {@code null} if no specification title exists. * @param specificationVersion The specification version of the package or {@code null} if no specification version exists. * @param specificationVendor The specification vendor of the package or {@code null} if no specification vendor exists. * @param implementationTitle The implementation title of the package or {@code null} if no implementation title exists. * @param implementationVersion The implementation version of the package or {@code null} if no implementation version exists. * @param implementationVendor The implementation vendor of the package or {@code null} if no implementation vendor exists. * @param sealBase The seal base URL or {@code null} if the package should not be sealed. * @return The defined package. */ Package definePackage(ClassLoader classLoader, String name, String specificationTitle, String specificationVersion, String specificationVendor, String implementationTitle, String implementationVersion, String implementationVendor, URL sealBase); /** * Initializes a dispatcher to make non-accessible APIs accessible. */ interface Initializable { /** * Indicates if this dispatcher is available. * * @return {@code true} if this dispatcher is available. */ boolean isAvailable(); /** * Initializes this dispatcher. * * @return The initiailized dispatcher. */ Dispatcher initialize(); } /** * A creation action for a dispatcher. */ enum CreationAction implements PrivilegedAction<Initializable> { /** * The singelton instance. */ INSTANCE; @Override public Initializable run() { try { return ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V9) ? Dispatcher.Indirect.make() : Dispatcher.Direct.make(); } catch (Exception exception) { return new Unavailable(exception); } } } /** * A class injection dispatcher that is using reflection on the {@link ClassLoader} methods. */ abstract class Direct implements Dispatcher, Initializable { /** * An instance of {@link ClassLoader#findLoadedClass(String)}. */ protected final Method findLoadedClass; /** * An instance of {@link ClassLoader#defineClass(String, byte[], int, int, ProtectionDomain)}. */ protected final Method defineClass; /** * An instance of {@link ClassLoader#getPackage(String)} or {@code ClassLoader#getDefinedPackage(String)}. */ protected final Method getPackage; /** * An instance of {@link ClassLoader#definePackage(String, String, String, String, String, String, String, URL)}. */ protected final Method definePackage; /** * Creates a new direct injection dispatcher. * * @param findLoadedClass An instance of {@link ClassLoader#findLoadedClass(String)}. * @param defineClass An instance of {@link ClassLoader#defineClass(String, byte[], int, int, ProtectionDomain)}. * @param getPackage An instance of {@link ClassLoader#getPackage(String)} or {@code ClassLoader#getDefinedPackage(String)}. * @param definePackage An instance of {@link ClassLoader#definePackage(String, String, String, String, String, String, String, URL)}. */ protected Direct(Method findLoadedClass, Method defineClass, Method getPackage, Method definePackage) { this.findLoadedClass = findLoadedClass; this.defineClass = defineClass; this.getPackage = getPackage; this.definePackage = definePackage; } protected static Initializable make() throws Exception { Method getPackage; try { getPackage = ClassLoader.class.getDeclaredMethod("getDefinedPackage", String.class); } catch (NoSuchMethodException ignored) { getPackage = ClassLoader.class.getDeclaredMethod("getPackage", String.class); } Method findLoadedClass = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ProtectionDomain.class); Method definePackage = ClassLoader.class.getDeclaredMethod("definePackage", String.class, String.class, String.class, String.class, String.class, String.class, String.class, URL.class); try { return new ForJava7CapableVm(findLoadedClass, defineClass, getPackage, definePackage, ClassLoader.class.getDeclaredMethod("getClassLoadingLock", String.class)); } catch (NoSuchMethodException ignored) { return new ForLegacyVm(findLoadedClass, defineClass, getPackage, definePackage); } } @Override public Class<?> findClass(ClassLoader classLoader, String name) { try { return (Class<?>) findLoadedClass.invoke(classLoader, name); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access java.lang.ClassLoader#findClass", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.ClassLoader#findClass", exception.getCause()); } } @Override public Class<?> defineClass(ClassLoader classLoader, String name, byte[] binaryRepresentation, ProtectionDomain protectionDomain) { try { return (Class<?>) defineClass.invoke(classLoader, name, binaryRepresentation, 0, binaryRepresentation.length, protectionDomain); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access java.lang.ClassLoader#findClass", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.ClassLoader#findClass", exception.getCause()); } } @Override public Package getPackage(ClassLoader classLoader, String name) { try { return (Package) getPackage.invoke(classLoader, name); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access java.lang.ClassLoader#findClass", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.ClassLoader#findClass", exception.getCause()); } } @Override public Package definePackage(ClassLoader classLoader, String name, String specificationTitle, String specificationVersion, String specificationVendor, String implementationTitle, String implementationVersion, String implementationVendor, URL sealBase) { try { return (Package) definePackage.invoke(classLoader, name, specificationTitle, specificationVersion, specificationVendor, implementationTitle, implementationVersion, implementationVendor, sealBase); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access java.lang.ClassLoader#findClass", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.ClassLoader#findClass", exception.getCause()); } } @Override public boolean isAvailable() { return true; } @Override public Dispatcher initialize() { try { // This is safe even in a multi-threaded environment as all threads set the instances accessible before invoking any methods. // By always setting accessibility, the security manager is always triggered if this operation was illegal. /** * Creates a direct dispatcher. * * @return A direct dispatcher for class injection. * @throws Exception If the creation is impossible. */ findLoadedClass.setAccessible(true); defineClass.setAccessible(true); getPackage.setAccessible(true); definePackage.setAccessible(true); onInitialization(); return this; } catch (Exception exception) { return new Unavailable(exception); } } /** * Invoked upon initializing methods. */ protected abstract void onInitialization(); /** * A resolved class dispatcher for a class injector on a VM running at least Java 7. */ protected static class ForJava7CapableVm extends Direct { /** * An instance of {@code ClassLoader#getClassLoadingLock(String)}. */ private final Method getClassLoadingLock; /** * Creates a new resolved reflection store for a VM running at least Java 7. * * @param getClassLoadingLock An instance of {@code ClassLoader#getClassLoadingLock(String)}. * @param findLoadedClass An instance of {@link ClassLoader#findLoadedClass(String)}. * @param defineClass An instance of {@link ClassLoader#defineClass(String, byte[], int, int, ProtectionDomain)}. * @param getPackage An instance of {@link ClassLoader#getPackage(String)} or {@code ClassLoader#getDefinedPackage(String)}. * @param definePackage An instance of {@link ClassLoader#definePackage(String, String, String, String, String, String, String, URL)}. */ protected ForJava7CapableVm(Method findLoadedClass, Method defineClass, Method getPackage, Method definePackage, Method getClassLoadingLock) { super(findLoadedClass, defineClass, getPackage, definePackage); this.getClassLoadingLock = getClassLoadingLock; } @Override public Object getClassLoadingLock(ClassLoader classLoader, String name) { try { return getClassLoadingLock.invoke(classLoader, name); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access java.lang.ClassLoader#getClassLoadingLock", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.ClassLoader#getClassLoadingLock", exception.getCause()); } } @Override protected void onInitialization() { getClassLoadingLock.setAccessible(true); } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof ClassInjector.UsingReflection.Dispatcher.Direct.ForJava7CapableVm)) return false; final ClassInjector.UsingReflection.Dispatcher.Direct.ForJava7CapableVm other = (ClassInjector.UsingReflection.Dispatcher.Direct.ForJava7CapableVm) o; if (!other.canEqual((java.lang.Object) this)) return false; if (!super.equals(o)) return false; final java.lang.Object this$getClassLoadingLock = this.getClassLoadingLock; final java.lang.Object other$getClassLoadingLock = other.getClassLoadingLock; if (this$getClassLoadingLock == null ? other$getClassLoadingLock != null : !this$getClassLoadingLock.equals(other$getClassLoadingLock)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof ClassInjector.UsingReflection.Dispatcher.Direct.ForJava7CapableVm; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; result = result * PRIME + super.hashCode(); final java.lang.Object $getClassLoadingLock = this.getClassLoadingLock; result = result * PRIME + ($getClassLoadingLock == null ? 43 : $getClassLoadingLock.hashCode()); return result; } } /** * A resolved class dispatcher for a class injector prior to Java 7. */ protected static class ForLegacyVm extends Direct { protected ForLegacyVm(Method findLoadedClass, Method defineClass, Method getPackage, Method definePackage) { super(findLoadedClass, defineClass, getPackage, definePackage); } @Override public Object getClassLoadingLock(ClassLoader classLoader, String name) { return classLoader; } @Override protected void onInitialization() { /* do nothing */ /** * Creates a new resolved reflection store for a VM prior to Java 8. * * @param findLoadedClass An instance of {@link ClassLoader#findLoadedClass(String)}. * @param defineClass An instance of {@link ClassLoader#defineClass(String, byte[], int, int, ProtectionDomain)}. * @param getPackage An instance of {@link ClassLoader#getPackage(String)} or {@code ClassLoader#getDefinedPackage(String)}. * @param definePackage An instance of {@link ClassLoader#definePackage(String, String, String, String, String, String, String, URL)}. */ } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof ClassInjector.UsingReflection.Dispatcher.Direct)) return false; final ClassInjector.UsingReflection.Dispatcher.Direct other = (ClassInjector.UsingReflection.Dispatcher.Direct) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$findLoadedClass = this.findLoadedClass; final java.lang.Object other$findLoadedClass = other.findLoadedClass; if (this$findLoadedClass == null ? other$findLoadedClass != null : !this$findLoadedClass.equals(other$findLoadedClass)) return false; final java.lang.Object this$defineClass = this.defineClass; final java.lang.Object other$defineClass = other.defineClass; if (this$defineClass == null ? other$defineClass != null : !this$defineClass.equals(other$defineClass)) return false; final java.lang.Object this$getPackage = this.getPackage; final java.lang.Object other$getPackage = other.getPackage; if (this$getPackage == null ? other$getPackage != null : !this$getPackage.equals(other$getPackage)) return false; final java.lang.Object this$definePackage = this.definePackage; final java.lang.Object other$definePackage = other.definePackage; if (this$definePackage == null ? other$definePackage != null : !this$definePackage.equals(other$definePackage)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof ClassInjector.UsingReflection.Dispatcher.Direct; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $findLoadedClass = this.findLoadedClass; result = result * PRIME + ($findLoadedClass == null ? 43 : $findLoadedClass.hashCode()); final java.lang.Object $defineClass = this.defineClass; result = result * PRIME + ($defineClass == null ? 43 : $defineClass.hashCode()); final java.lang.Object $getPackage = this.getPackage; result = result * PRIME + ($getPackage == null ? 43 : $getPackage.hashCode()); final java.lang.Object $definePackage = this.definePackage; result = result * PRIME + ($definePackage == null ? 43 : $definePackage.hashCode()); return result; } } /** * An indirect dispatcher that uses a redirection accessor class that was injected into the bootstrap class loader. */ class Indirect implements Dispatcher, Initializable { /** * The access permission to check upon injection if a security manager is active. */ private static final Permission ACCESS_PERMISSION = new ReflectPermission("suppressAccessChecks"); /** * An instance of the accessor class that is required for using it's intentionally non-static methods. */ private final Object accessor; /** * The accessor method for using {@link ClassLoader#findLoadedClass(String)}. */ private final Method findLoadedClass; /** * The accessor method for using {@link ClassLoader#defineClass(String, byte[], int, int, ProtectionDomain)}. */ private final Method defineClass; /** * The accessor method for using {@link ClassLoader#getPackage(String)} or {@code ClassLoader#getDefinedPackage(String)}. */ private final Method getPackage; /** * The accessor method for using {@link ClassLoader#definePackage(String, String, String, String, String, String, String, URL)}. */ private final Method definePackage; /** * The accessor method for using {@code ClassLoader#getClassLoadingLock(String)} or returning the supplied {@link ClassLoader} * if this method does not exist on the current VM. */ private final Method getClassLoadingLock; /** * Creates a new indirect class loading injection dispatcher. * * @param accessor An instance of the accessor class that is required for using it's intentionally non-static methods. * @param findLoadedClass An instance of {@link ClassLoader#findLoadedClass(String)}. * @param defineClass An instance of {@link ClassLoader#defineClass(String, byte[], int, int, ProtectionDomain)}. * @param getPackage An instance of {@link ClassLoader#getPackage(String)} or {@code ClassLoader#getDefinedPackage(String)}. * @param definePackage An instance of {@link ClassLoader#definePackage(String, String, String, String, String, String, String, URL)}. * @param getClassLoadingLock The accessor method for using {@code ClassLoader#getClassLoadingLock(String)} or returning the * supplied {@link ClassLoader} if this method does not exist on the current VM. */ protected Indirect(Object accessor, Method findLoadedClass, Method defineClass, Method getPackage, Method definePackage, Method getClassLoadingLock) { this.accessor = accessor; this.findLoadedClass = findLoadedClass; this.defineClass = defineClass; this.getPackage = getPackage; this.definePackage = definePackage; this.getClassLoadingLock = getClassLoadingLock; } @Override public boolean isAvailable() { return true; } /** * Creates an indirect dispatcher. * * @return An indirect dispatcher for class creation. * @throws Exception If the dispatcher cannot be created. */ public static Initializable make() throws Exception { Class<?> unsafe = Class.forName("sun.misc.Unsafe"); Field theUnsafe = unsafe.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Object unsafeInstance = theUnsafe.get(null); Method getPackage; try { getPackage = ClassLoader.class.getDeclaredMethod("getDeclaredPackage", String.class); } catch (NoSuchMethodException ignored) { getPackage = ClassLoader.class.getDeclaredMethod("getPackage", String.class); } DynamicType.Builder<?> builder = new ByteBuddy().subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS).name(ClassLoader.class.getName() + "$ByteBuddyAccessor$" + RandomString.make()).defineMethod("findLoadedClass", Class.class, Visibility.PUBLIC).withParameters(ClassLoader.class, String.class).intercept(MethodCall.invoke(ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class)).onArgument(0).withArgument(1)).defineMethod("defineClass", Class.class, Visibility.PUBLIC).withParameters(ClassLoader.class, String.class, byte[].class, int.class, int.class, ProtectionDomain.class).intercept(MethodCall.invoke(ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ProtectionDomain.class)).onArgument(0).withArgument(1, 2, 3, 4, 5)).defineMethod("getPackage", Package.class, Visibility.PUBLIC).withParameters(ClassLoader.class, String.class).intercept(MethodCall.invoke(getPackage).onArgument(0).withArgument(1)).defineMethod("definePackage", Package.class, Visibility.PUBLIC).withParameters(ClassLoader.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, URL.class).intercept(MethodCall.invoke(ClassLoader.class.getDeclaredMethod("definePackage", String.class, String.class, String.class, String.class, String.class, String.class, String.class, URL.class)).onArgument(0).withArgument(1, 2, 3, 4, 5, 6, 7, 8)); try { builder = builder.defineMethod("getClassLoadingLock", Object.class, Visibility.PUBLIC).withParameters(ClassLoader.class, String.class).intercept(MethodCall.invoke(ClassLoader.class.getDeclaredMethod("getClassLoadingLock", String.class)).onArgument(0).withArgument(1)); } catch (NoSuchMethodException ignored) { builder = builder.defineMethod("getClassLoadingLock", Object.class, Visibility.PUBLIC).withParameters(ClassLoader.class, String.class).intercept(FixedValue.argument(0)); } Class<?> type = builder.make().load(ClassLoadingStrategy.BOOTSTRAP_LOADER, new ClassLoadingStrategy.ForUnsafeInjection()).getLoaded(); return new Indirect(unsafe.getDeclaredMethod("allocateInstance", Class.class).invoke(unsafeInstance, type), type.getMethod("findLoadedClass", ClassLoader.class, String.class), type.getMethod("defineClass", ClassLoader.class, String.class, byte[].class, int.class, int.class, ProtectionDomain.class), type.getMethod("getPackage", ClassLoader.class, String.class), type.getMethod("definePackage", ClassLoader.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, URL.class), type.getMethod("getClassLoadingLock", ClassLoader.class, String.class)); } @Override public Dispatcher initialize() { SecurityManager securityManager = System.getSecurityManager(); if (securityManager != null) { securityManager.checkPermission(ACCESS_PERMISSION); } return this; } @Override public Object getClassLoadingLock(ClassLoader classLoader, String name) { try { return getClassLoadingLock.invoke(accessor, classLoader, name); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access (accessor)::getClassLoadingLock", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking (accessor)::getClassLoadingLock", exception.getCause()); } } @Override public Class<?> findClass(ClassLoader classLoader, String name) { try { return (Class<?>) findLoadedClass.invoke(accessor, classLoader, name); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access (accessor)::findLoadedClass", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking (accessor)::findLoadedClass", exception.getCause()); } } @Override public Class<?> defineClass(ClassLoader classLoader, String name, byte[] binaryRepresentation, ProtectionDomain protectionDomain) { try { return (Class<?>) defineClass.invoke(accessor, classLoader, name, binaryRepresentation, 0, binaryRepresentation.length, protectionDomain); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access (accessor)::defineClass", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking (accessor)::defineClass", exception.getCause()); } } @Override public Package getPackage(ClassLoader classLoader, String name) { try { return (Package) getPackage.invoke(accessor, classLoader, name); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access (accessor)::getPackage", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking (accessor)::getPackage", exception.getCause()); } } @Override public Package definePackage(ClassLoader classLoader, String name, String specificationTitle, String specificationVersion, String specificationVendor, String implementationTitle, String implementationVersion, String implementationVendor, URL sealBase) { try { return (Package) definePackage.invoke(accessor, classLoader, name, specificationTitle, specificationVersion, specificationVendor, implementationTitle, implementationVersion, implementationVendor, sealBase); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access (accessor)::definePackage", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking (accessor)::definePackage", exception.getCause()); } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof ClassInjector.UsingReflection.Dispatcher.Indirect)) return false; final ClassInjector.UsingReflection.Dispatcher.Indirect other = (ClassInjector.UsingReflection.Dispatcher.Indirect) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$accessor = this.accessor; final java.lang.Object other$accessor = other.accessor; if (this$accessor == null ? other$accessor != null : !this$accessor.equals(other$accessor)) return false; final java.lang.Object this$findLoadedClass = this.findLoadedClass; final java.lang.Object other$findLoadedClass = other.findLoadedClass; if (this$findLoadedClass == null ? other$findLoadedClass != null : !this$findLoadedClass.equals(other$findLoadedClass)) return false; final java.lang.Object this$defineClass = this.defineClass; final java.lang.Object other$defineClass = other.defineClass; if (this$defineClass == null ? other$defineClass != null : !this$defineClass.equals(other$defineClass)) return false; final java.lang.Object this$getPackage = this.getPackage; final java.lang.Object other$getPackage = other.getPackage; if (this$getPackage == null ? other$getPackage != null : !this$getPackage.equals(other$getPackage)) return false; final java.lang.Object this$definePackage = this.definePackage; final java.lang.Object other$definePackage = other.definePackage; if (this$definePackage == null ? other$definePackage != null : !this$definePackage.equals(other$definePackage)) return false; final java.lang.Object this$getClassLoadingLock = this.getClassLoadingLock; final java.lang.Object other$getClassLoadingLock = other.getClassLoadingLock; if (this$getClassLoadingLock == null ? other$getClassLoadingLock != null : !this$getClassLoadingLock.equals(other$getClassLoadingLock)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof ClassInjector.UsingReflection.Dispatcher.Indirect; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $accessor = this.accessor; result = result * PRIME + ($accessor == null ? 43 : $accessor.hashCode()); final java.lang.Object $findLoadedClass = this.findLoadedClass; result = result * PRIME + ($findLoadedClass == null ? 43 : $findLoadedClass.hashCode()); final java.lang.Object $defineClass = this.defineClass; result = result * PRIME + ($defineClass == null ? 43 : $defineClass.hashCode()); final java.lang.Object $getPackage = this.getPackage; result = result * PRIME + ($getPackage == null ? 43 : $getPackage.hashCode()); final java.lang.Object $definePackage = this.definePackage; result = result * PRIME + ($definePackage == null ? 43 : $definePackage.hashCode()); final java.lang.Object $getClassLoadingLock = this.getClassLoadingLock; result = result * PRIME + ($getClassLoadingLock == null ? 43 : $getClassLoadingLock.hashCode()); return result; } } /** * Represents an unsuccessfully loaded method lookup. */ class Unavailable implements Dispatcher, Initializable { /** * The exception that occurred when looking up the reflection methods. */ private final Exception exception; /** * Creates a new faulty reflection store. * * @param exception The exception that was thrown when attempting to lookup the method. */ protected Unavailable(Exception exception) { this.exception = exception; } @Override public boolean isAvailable() { return false; } @Override public Dispatcher initialize() { return this; } @Override public Object getClassLoadingLock(ClassLoader classLoader, String name) { return classLoader; } @Override public Class<?> findClass(ClassLoader classLoader, String name) { try { return classLoader.loadClass(name); } catch (ClassNotFoundException ignored) { return UNDEFINED; } } @Override public Class<?> defineClass(ClassLoader classLoader, String name, byte[] binaryRepresentation, ProtectionDomain protectionDomain) { throw new UnsupportedOperationException("Cannot define class using reflection", exception); } @Override public Package getPackage(ClassLoader classLoader, String name) { throw new UnsupportedOperationException("Cannot get package using reflection", exception); } @Override public Package definePackage(ClassLoader classLoader, String name, String specificationTitle, String specificationVersion, String specificationVendor, String implementationTitle, String implementationVersion, String implementationVendor, URL sealBase) { throw new UnsupportedOperationException("Cannot define package using injection", exception); } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof ClassInjector.UsingReflection.Dispatcher.Unavailable)) return false; final ClassInjector.UsingReflection.Dispatcher.Unavailable other = (ClassInjector.UsingReflection.Dispatcher.Unavailable) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$exception = this.exception; final java.lang.Object other$exception = other.exception; if (this$exception == null ? other$exception != null : !this$exception.equals(other$exception)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof ClassInjector.UsingReflection.Dispatcher.Unavailable; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $exception = this.exception; result = result * PRIME + ($exception == null ? 43 : $exception.hashCode()); return result; } } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof ClassInjector.UsingReflection)) return false; final ClassInjector.UsingReflection other = (ClassInjector.UsingReflection) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$classLoader = this.classLoader; final java.lang.Object other$classLoader = other.classLoader; if (this$classLoader == null ? other$classLoader != null : !this$classLoader.equals(other$classLoader)) return false; final java.lang.Object this$protectionDomain = this.protectionDomain; final java.lang.Object other$protectionDomain = other.protectionDomain; if (this$protectionDomain == null ? other$protectionDomain != null : !this$protectionDomain.equals(other$protectionDomain)) return false; final java.lang.Object this$packageDefinitionStrategy = this.packageDefinitionStrategy; final java.lang.Object other$packageDefinitionStrategy = other.packageDefinitionStrategy; if (this$packageDefinitionStrategy == null ? other$packageDefinitionStrategy != null : !this$packageDefinitionStrategy.equals(other$packageDefinitionStrategy)) return false; if (this.forbidExisting != other.forbidExisting) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof ClassInjector.UsingReflection; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $classLoader = this.classLoader; result = result * PRIME + ($classLoader == null ? 43 : $classLoader.hashCode()); final java.lang.Object $protectionDomain = this.protectionDomain; result = result * PRIME + ($protectionDomain == null ? 43 : $protectionDomain.hashCode()); final java.lang.Object $packageDefinitionStrategy = this.packageDefinitionStrategy; result = result * PRIME + ($packageDefinitionStrategy == null ? 43 : $packageDefinitionStrategy.hashCode()); result = result * PRIME + (this.forbidExisting ? 79 : 97); return result; } } /** * A class injector that uses {@code sun.misc.Unsafe} to inject classes. */ class UsingUnsafe implements ClassInjector { /** * The dispatcher to use. */ private static final Dispatcher.Initializable DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE); /** * A lock for the bootstrap loader when injecting code. */ private static final Object BOOTSTRAP_LOADER_LOCK = new Object(); /** * The class loader to inject classes into or {@code null} for the bootstrap loader. */ private final ClassLoader classLoader; /** * The protection domain to use or {@code null} for no protection domain. */ private final ProtectionDomain protectionDomain; /** * Creates a new unsafe injector for the given class loader with a default protection domain. * * @param classLoader The class loader to inject classes into or {@code null} for the bootstrap loader. */ public UsingUnsafe(ClassLoader classLoader) { this(classLoader, ClassLoadingStrategy.NO_PROTECTION_DOMAIN); } /** * Creates a new unsafe injector for the given class loader with a default protection domain. * * @param classLoader The class loader to inject classes into or {@code null} for the bootstrap loader. * @param protectionDomain The protection domain to use or {@code null} for no protection domain. */ public UsingUnsafe(ClassLoader classLoader, ProtectionDomain protectionDomain) { this.classLoader = classLoader; this.protectionDomain = protectionDomain; } /** * Checks if unsafe class injection is available on the current VM. * * @return {@code true} if unsafe class injection is available on the current VM. */ public static boolean isAvailable() { return DISPATCHER.isAvailable(); } /** * Returns an unsafe class injector for the bootstrap class loader. * * @return A class injector for the bootstrap loader. */ public static ClassInjector ofBootstrapLoader() { return new UsingUnsafe(ClassLoadingStrategy.BOOTSTRAP_LOADER); } /** * Returns an unsafe class injector for the class path. * * @return A class injector for the system class loader. */ public static ClassInjector ofClassPath() { return new UsingUnsafe(ClassLoader.getSystemClassLoader()); } @Override public Map<TypeDescription, Class<?>> inject(Map<? extends TypeDescription, byte[]> types) { Dispatcher dispatcher = DISPATCHER.initialize(); Map<TypeDescription, Class<?>> loaded = new HashMap<TypeDescription, Class<?>>(); synchronized (classLoader == null ? BOOTSTRAP_LOADER_LOCK : classLoader) { for (Map.Entry<? extends TypeDescription, byte[]> entry : types.entrySet()) { try { loaded.put(entry.getKey(), Class.forName(entry.getKey().getName(), false, classLoader)); } catch (ClassNotFoundException ignored) { loaded.put(entry.getKey(), dispatcher.defineClass(classLoader, entry.getKey().getName(), entry.getValue(), protectionDomain)); } } } return loaded; } /** * A dispatcher for using {@code sun.misc.Unsafe}. */ interface Dispatcher { /** * Defines a class. * * @param classLoader The class loader to inject the class into. * @param name The type's name. * @param binaryRepresentation The type's binary representation. * @param protectionDomain The type's protection domain. * @return The defined class. */ Class<?> defineClass(ClassLoader classLoader, String name, byte[] binaryRepresentation, ProtectionDomain protectionDomain); /** * A class injection dispatcher that is not yet initialized. */ interface Initializable { /** * Checks if unsafe class injection is available on the current VM. * * @return {@code true} if unsafe class injection is available. */ boolean isAvailable(); /** * Initializes the dispatcher. * * @return The initialized dispatcher. */ Dispatcher initialize(); } /** * A privileged action for creating a dispatcher. */ enum CreationAction implements PrivilegedAction<Initializable> { /** * The singleton instance. */ INSTANCE; @Override public Initializable run() { try { Class<?> unsafe = Class.forName("sun.misc.Unsafe"); return new Enabled(unsafe.getDeclaredField("theUnsafe"), unsafe.getMethod("defineClass", String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class)); } catch (Exception exception) { return new Disabled(exception); } } } /** * An enabled dispatcher. */ class Enabled implements Dispatcher, Initializable { /** * A field containing {@code sun.misc.Unsafe}. */ private final Field theUnsafe; /** * The {@code sun.misc.Unsafe#defineClass} method. */ private final Method defineClass; /** * Creates an enabled dispatcher. * * @param theUnsafe A field containing {@code sun.misc.Unsafe}. * @param defineClass The {@code sun.misc.Unsafe#defineClass} method. */ protected Enabled(Field theUnsafe, Method defineClass) { this.theUnsafe = theUnsafe; this.defineClass = defineClass; } @Override public boolean isAvailable() { return true; } @Override public Dispatcher initialize() { theUnsafe.setAccessible(true); return this; } @Override public Class<?> defineClass(ClassLoader classLoader, String name, byte[] binaryRepresentation, ProtectionDomain protectionDomain) { try { return (Class<?>) defineClass.invoke(theUnsafe.get(null), name, binaryRepresentation, 0, binaryRepresentation.length, classLoader, protectionDomain); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access Unsafe::defineClass", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking Unsafe::defineClass", exception.getCause()); } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof ClassInjector.UsingUnsafe.Dispatcher.Enabled)) return false; final ClassInjector.UsingUnsafe.Dispatcher.Enabled other = (ClassInjector.UsingUnsafe.Dispatcher.Enabled) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$theUnsafe = this.theUnsafe; final java.lang.Object other$theUnsafe = other.theUnsafe; if (this$theUnsafe == null ? other$theUnsafe != null : !this$theUnsafe.equals(other$theUnsafe)) return false; final java.lang.Object this$defineClass = this.defineClass; final java.lang.Object other$defineClass = other.defineClass; if (this$defineClass == null ? other$defineClass != null : !this$defineClass.equals(other$defineClass)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof ClassInjector.UsingUnsafe.Dispatcher.Enabled; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $theUnsafe = this.theUnsafe; result = result * PRIME + ($theUnsafe == null ? 43 : $theUnsafe.hashCode()); final java.lang.Object $defineClass = this.defineClass; result = result * PRIME + ($defineClass == null ? 43 : $defineClass.hashCode()); return result; } } /** * A disabled dispatcher. */ class Disabled implements Initializable { /** * The exception causing this dispatcher's creation. */ private final Exception exception; /** * Creates a disabled dispatcher. * * @param exception The exception causing this dispatcher's creation. */ protected Disabled(Exception exception) { this.exception = exception; } @Override public boolean isAvailable() { return false; } @Override public Dispatcher initialize() { throw new IllegalStateException("Could not find sun.misc.Unsafe", exception); } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof ClassInjector.UsingUnsafe.Dispatcher.Disabled)) return false; final ClassInjector.UsingUnsafe.Dispatcher.Disabled other = (ClassInjector.UsingUnsafe.Dispatcher.Disabled) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$exception = this.exception; final java.lang.Object other$exception = other.exception; if (this$exception == null ? other$exception != null : !this$exception.equals(other$exception)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof ClassInjector.UsingUnsafe.Dispatcher.Disabled; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $exception = this.exception; result = result * PRIME + ($exception == null ? 43 : $exception.hashCode()); return result; } } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof ClassInjector.UsingUnsafe)) return false; final ClassInjector.UsingUnsafe other = (ClassInjector.UsingUnsafe) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$classLoader = this.classLoader; final java.lang.Object other$classLoader = other.classLoader; if (this$classLoader == null ? other$classLoader != null : !this$classLoader.equals(other$classLoader)) return false; final java.lang.Object this$protectionDomain = this.protectionDomain; final java.lang.Object other$protectionDomain = other.protectionDomain; if (this$protectionDomain == null ? other$protectionDomain != null : !this$protectionDomain.equals(other$protectionDomain)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof ClassInjector.UsingUnsafe; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $classLoader = this.classLoader; result = result * PRIME + ($classLoader == null ? 43 : $classLoader.hashCode()); final java.lang.Object $protectionDomain = this.protectionDomain; result = result * PRIME + ($protectionDomain == null ? 43 : $protectionDomain.hashCode()); return result; } } /** * A class injector using a {@link java.lang.instrument.Instrumentation} to append to either the boot classpath * or the system class path. */ class UsingInstrumentation implements ClassInjector { /** * A prefix to use of generated files. */ private static final String PREFIX = "jar"; /** * The class file extension. */ private static final String CLASS_FILE_EXTENSION = ".class"; /** * The instrumentation to use for appending to the class path or the boot path. */ private final Instrumentation instrumentation; /** * A representation of the target path to which classes are to be appended. */ private final Target target; /** * The folder to be used for storing jar files. */ private final File folder; /** * A random string generator for creating file names. */ private final RandomString randomString; /** * Creates an instrumentation-based class injector. * * @param folder The folder to be used for storing jar files. * @param target A representation of the target path to which classes are to be appended. * @param instrumentation The instrumentation to use for appending to the class path or the boot path. * @return An appropriate class injector that applies instrumentation. */ public static ClassInjector of(File folder, Target target, Instrumentation instrumentation) { return new UsingInstrumentation(folder, target, instrumentation, new RandomString()); } /** * Creates an instrumentation-based class injector. * * @param folder The folder to be used for storing jar files. * @param target A representation of the target path to which classes are to be appended. * @param instrumentation The instrumentation to use for appending to the class path or the boot path. * @param randomString The random string generator to use. */ protected UsingInstrumentation(File folder, Target target, Instrumentation instrumentation, RandomString randomString) { this.folder = folder; this.target = target; this.instrumentation = instrumentation; this.randomString = randomString; } @Override public Map<TypeDescription, Class<?>> inject(Map<? extends TypeDescription, byte[]> types) { File jarFile = new File(folder, String.format("%s%s.jar", PREFIX, randomString.nextString())); try { if (!jarFile.createNewFile()) { throw new IllegalStateException("Cannot create file " + jarFile); } JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(jarFile)); try { for (Map.Entry<? extends TypeDescription, byte[]> entry : types.entrySet()) { jarOutputStream.putNextEntry(new JarEntry(entry.getKey().getInternalName() + CLASS_FILE_EXTENSION)); jarOutputStream.write(entry.getValue()); } } finally { jarOutputStream.close(); } target.inject(instrumentation, new JarFile(jarFile)); Map<TypeDescription, Class<?>> loaded = new HashMap<TypeDescription, Class<?>>(); for (TypeDescription typeDescription : types.keySet()) { loaded.put(typeDescription, Class.forName(typeDescription.getName(), false, ClassLoader.getSystemClassLoader())); } return loaded; } catch (IOException exception) { throw new IllegalStateException("Cannot write jar file to disk", exception); } catch (ClassNotFoundException exception) { throw new IllegalStateException("Cannot load injected class", exception); } } /** * A representation of the target to which Java classes should be appended to. */ public enum Target { /** * Representation of the bootstrap class loader. */ BOOTSTRAP { @Override protected void inject(Instrumentation instrumentation, JarFile jarFile) { instrumentation.appendToBootstrapClassLoaderSearch(jarFile); } }, /** * Representation of the system class loader. */ SYSTEM { @Override protected void inject(Instrumentation instrumentation, JarFile jarFile) { instrumentation.appendToSystemClassLoaderSearch(jarFile); } }; /** * Adds the given classes to the represented class loader. * * @param instrumentation The instrumentation instance to use. * @param jarFile The jar file to append. */ protected abstract void inject(Instrumentation instrumentation, JarFile jarFile); } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof ClassInjector.UsingInstrumentation)) return false; final ClassInjector.UsingInstrumentation other = (ClassInjector.UsingInstrumentation) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$instrumentation = this.instrumentation; final java.lang.Object other$instrumentation = other.instrumentation; if (this$instrumentation == null ? other$instrumentation != null : !this$instrumentation.equals(other$instrumentation)) return false; final java.lang.Object this$target = this.target; final java.lang.Object other$target = other.target; if (this$target == null ? other$target != null : !this$target.equals(other$target)) return false; final java.lang.Object this$folder = this.folder; final java.lang.Object other$folder = other.folder; if (this$folder == null ? other$folder != null : !this$folder.equals(other$folder)) return false; final java.lang.Object this$randomString = this.randomString; final java.lang.Object other$randomString = other.randomString; if (this$randomString == null ? other$randomString != null : !this$randomString.equals(other$randomString)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof ClassInjector.UsingInstrumentation; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $instrumentation = this.instrumentation; result = result * PRIME + ($instrumentation == null ? 43 : $instrumentation.hashCode()); final java.lang.Object $target = this.target; result = result * PRIME + ($target == null ? 43 : $target.hashCode()); final java.lang.Object $folder = this.folder; result = result * PRIME + ($folder == null ? 43 : $folder.hashCode()); final java.lang.Object $randomString = this.randomString; result = result * PRIME + ($randomString == null ? 43 : $randomString.hashCode()); return result; } } }