All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.bytebuddy.asm.MemberRemoval Maven / Gradle / Ivy

There is a newer version: 1.49.0
Show newest version
/*
 * 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.asm;

import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.pool.TypePool;
import net.bytebuddy.utility.CompoundList;
import net.bytebuddy.utility.OpenedClassReader;
import net.bytebuddy.utility.nullability.AlwaysNull;
import net.bytebuddy.utility.nullability.MaybeNull;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

import java.util.HashMap;
import java.util.Map;

import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;

/**
 * 

* A visitor wrapper that removes fields or methods that match a given {@link ElementMatcher}. *

*

* Important: This matcher is not capable of removing synthetic bridge methods which will be retained if they are * declared by the same class. As bridge methods only invoke an overridden method, the dispatch should however not be * influenced by their retention. *

*

* Important: The removal of the method is not reflected in the created {@link net.bytebuddy.dynamic.DynamicType}'s * type description of the instrumented type. *

*/ @HashCodeAndEqualsPlugin.Enhance public class MemberRemoval extends AsmVisitorWrapper.AbstractBase { /** * The matcher that decides upon field removal. */ private final ElementMatcher.Junction fieldMatcher; /** * The matcher that decides upon method removal. */ private final ElementMatcher.Junction methodMatcher; /** * Creates a new member removal instance that does not specify the removal of any methods. */ public MemberRemoval() { this(ElementMatchers.none(), ElementMatchers.none()); } /** * Creates a new member removal instance. * * @param fieldMatcher The matcher that decides upon field removal. * @param methodMatcher The matcher that decides upon field removal. */ protected MemberRemoval(ElementMatcher.Junction fieldMatcher, ElementMatcher.Junction methodMatcher) { this.fieldMatcher = fieldMatcher; this.methodMatcher = methodMatcher; } /** * Specifies that any field that matches the specified matcher should be removed. * * @param matcher The matcher that decides upon field removal. * @return A new member removal instance that removes all previously specified members and any fields that match the specified matcher. */ public MemberRemoval stripFields(ElementMatcher matcher) { return new MemberRemoval(fieldMatcher.or(matcher), methodMatcher); } /** * Specifies that any method that matches the specified matcher should be removed. Note that this implementation will * not strip bridge methods for virtual overrides of generic methods. * * @param matcher The matcher that decides upon method removal. * @return A new member removal instance that removes all previously specified members and any method that matches the specified matcher. */ public MemberRemoval stripMethods(ElementMatcher matcher) { return stripInvokables(isMethod().and(matcher)); } /** * Specifies that any constructor that matches the specified matcher should be removed. * * @param matcher The matcher that decides upon constructor removal. * @return A new member removal instance that removes all previously specified members and any constructor that matches the specified matcher. */ public MemberRemoval stripConstructors(ElementMatcher matcher) { return stripInvokables(isConstructor().and(matcher)); } /** * Specifies that any method or constructor that matches the specified matcher should be removed. Note that this implementation will * not strip bridge methods for virtual overrides of generic methods. * * @param matcher The matcher that decides upon method and constructor removal. * @return A new member removal instance that removes all previously specified members and any method or constructor that matches the specified matcher. */ public MemberRemoval stripInvokables(ElementMatcher matcher) { return new MemberRemoval(fieldMatcher, methodMatcher.or(matcher)); } /** * {@inheritDoc} */ public ClassVisitor wrap(TypeDescription instrumentedType, ClassVisitor classVisitor, Implementation.Context implementationContext, TypePool typePool, FieldList fields, MethodList methods, int writerFlags, int readerFlags) { Map mappedFields = new HashMap(); for (FieldDescription.InDefinedShape fieldDescription : fields) { mappedFields.put(fieldDescription.getInternalName() + fieldDescription.getDescriptor(), fieldDescription); } Map mappedMethods = new HashMap(); for (MethodDescription methodDescription : CompoundList.of(methods, new MethodDescription.Latent.TypeInitializer(instrumentedType))) { mappedMethods.put(methodDescription.getInternalName() + methodDescription.getDescriptor(), methodDescription); } return new MemberRemovingClassVisitor(classVisitor, fieldMatcher, methodMatcher, mappedFields, mappedMethods); } /** * A class visitor that removes members based on element matchers. */ protected static class MemberRemovingClassVisitor extends ClassVisitor { /** * Indicates the removal of a field. */ @javax.annotation.Nonnull(when = javax.annotation.meta.When.NEVER) private static final FieldVisitor REMOVE_FIELD = null; /** * Indicates the removal of a method. */ @AlwaysNull private static final MethodVisitor REMOVE_METHOD = null; /** * The matcher that determines field removal. */ private final ElementMatcher.Junction fieldMatcher; /** * The matcher that determines method removal. */ private final ElementMatcher.Junction methodMatcher; /** * A mapping of field names and descriptors to their description. */ private final Map fields; /** * A mapping of method names and descriptors to their description. */ private final Map methods; /** * Creates a new member removing class visitor. * * @param classVisitor The class visitor to delegate to. * @param fieldMatcher The matcher that determines field removal. * @param methodMatcher The matcher that determines method removal. * @param fields A mapping of field names and descriptors to their description. * @param methods A mapping of method names and descriptors to their description. */ protected MemberRemovingClassVisitor(ClassVisitor classVisitor, ElementMatcher.Junction fieldMatcher, ElementMatcher.Junction methodMatcher, Map fields, Map methods) { super(OpenedClassReader.ASM_API, classVisitor); this.fieldMatcher = fieldMatcher; this.methodMatcher = methodMatcher; this.fields = fields; this.methods = methods; } @Override @MaybeNull public FieldVisitor visitField(int modifiers, String internalName, String descriptor, @MaybeNull String signature, @MaybeNull Object value) { FieldDescription.InDefinedShape fieldDescription = fields.get(internalName + descriptor); return fieldDescription != null && fieldMatcher.matches(fieldDescription) ? REMOVE_FIELD : super.visitField(modifiers, internalName, descriptor, signature, value); } @Override @MaybeNull public MethodVisitor visitMethod(int modifiers, String internalName, String descriptor, @MaybeNull String signature, @MaybeNull String[] exception) { MethodDescription methodDescription = methods.get(internalName + descriptor); return methodDescription != null && methodMatcher.matches(methodDescription) ? REMOVE_METHOD : super.visitMethod(modifiers, internalName, descriptor, signature, exception); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy