下面列出了怎么用org.objectweb.asm.ClassVisitor的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* {@inheritDoc}
*/
public void apply(ClassVisitor classVisitor, TypeDescription instrumentedType, AnnotationValueFilter annotationValueFilter) {
AnnotationAppender annotationAppender = new AnnotationAppender.Default(new AnnotationAppender.Target.OnType(classVisitor));
annotationAppender = AnnotationAppender.ForTypeAnnotations.ofTypeVariable(annotationAppender,
annotationValueFilter,
AnnotationAppender.ForTypeAnnotations.VARIABLE_ON_TYPE,
instrumentedType.getTypeVariables());
TypeDescription.Generic superClass = instrumentedType.getSuperClass();
if (superClass != null) {
annotationAppender = superClass.accept(AnnotationAppender.ForTypeAnnotations.ofSuperClass(annotationAppender, annotationValueFilter));
}
int interfaceIndex = 0;
for (TypeDescription.Generic interfaceType : instrumentedType.getInterfaces()) {
annotationAppender = interfaceType.accept(AnnotationAppender.ForTypeAnnotations.ofInterfaceType(annotationAppender,
annotationValueFilter,
interfaceIndex++));
}
for (AnnotationDescription annotation : instrumentedType.getDeclaredAnnotations()) {
annotationAppender = annotationAppender.append(annotation, annotationValueFilter);
}
}
@Override
public byte /*@Nullable*/ [] transform(@Nullable ClassLoader loader, @Nullable String className,
@Nullable Class<?> classBeingRedefined, @Nullable ProtectionDomain protectionDomain,
byte[] bytes) {
try {
if ("sun/misc/Launcher$AppClassLoader".equals(className)) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor cv = new DebuggingClassVisitor(cw);
ClassReader cr = new ClassReader(bytes);
cr.accept(cv, ClassReader.EXPAND_FRAMES);
return cw.toByteArray();
}
} catch (Throwable t) {
if (logger == null) {
t.printStackTrace();
} else {
logger.error(t.getMessage(), t);
}
}
return null;
}
/**
* Creates a new ConsumerGenerator.
*
* @param visitor The class visitor that will be visited with the generated Consumer class
* @param name The name of the class to generate
* @param descriptorA The descriptor of the first type parameter (T in Consumer<T>), for example
* "Ljava/lang/String;"
* @param descriptorB The descriptor of the second type parameter (T in Consumer<T>), for
* example "Ljava/lang/String;"
* @param signatureA The signature of the first type parameter, for example
* "Ljava/util/function/Consumer<Ljava/lang/String;>;"
* @param signatureB The signature of the second type parameter, for example
* "Ljava/util/function/Consumer<Ljava/lang/String;>;"
*/
public BiConsumerGenerator(ClassVisitor visitor, String name, String descriptorA, String descriptorB, String signatureA, String signatureB) {
this.visitor = visitor;
this.name = name;
this.descriptorA = descriptorA;
this.descriptorB = descriptorB;
this.signatureA = signatureA;
this.signatureB = signatureB;
if (signatureA == null) {
signatureA = descriptorA;
}
if (signatureB == null) {
signatureB = descriptorB;
}
visitor.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, name, "Ljava/lang/Object;Ljava/util/function/BiConsumer<" + signatureA + signatureB + ">;", "java/lang/Object", new String[] {
"java/util/function/BiConsumer" });
}
public void generateClass(ClassVisitor v) throws Exception {
ClassEmitter ce = new ClassEmitter(v);
ce.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
STRING_SWITCHER,
null,
Constants.SOURCE_FILE);
EmitUtils.null_constructor(ce);
final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, INT_VALUE, null);
e.load_arg(0);
final List stringList = Arrays.asList(strings);
int style = fixedInput ? Constants.SWITCH_STYLE_HASHONLY : Constants.SWITCH_STYLE_HASH;
EmitUtils.string_switch(e, strings, style, new ObjectSwitchCallback() {
public void processCase(Object key, Label end) {
e.push(ints[stringList.indexOf(key)]);
e.return_value();
}
public void processDefault() {
e.push(-1);
e.return_value();
}
});
e.end_method();
ce.end_class();
}
private static void implementProxyInstance(ClassVisitor classVisitor, Class<?> iFace, String generatedName) {
MethodVisitor methodVisitor = classVisitor.visitMethod(Opcodes.ACC_PUBLIC,
"proxyInstance",
methodDescriptor(iFace, iFace),
null,
null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(Opcodes.ALOAD, LOCALS_INDEX_THIS);
methodVisitor.visitInsn(Opcodes.ARETURN);
methodVisitor.visitMaxs(-1, -1);
methodVisitor.visitEnd();
implementBridgeMethod(classVisitor, generatedName, "proxyInstance", iFace, iFace);
}
@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
if (bytes == null) {
return null;
}
// check for any inner classes of NetworkManager. It differes between mc versions
if (transformedName.startsWith("net.minecraft.network.NetworkManager$")) {
try {
ClassReader classReader = new ClassReader(bytes);
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES);
ClassVisitor classVisitor = new NetworkManagerInnerVisitor(classWriter);
classReader.accept(classVisitor, ClassReader.SKIP_FRAMES);
return classWriter.toByteArray();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
return bytes;
}
/**
* {@inheritDoc}
*/
public ClassVisitor wrap(TypeDescription instrumentedType,
ClassVisitor classVisitor,
Implementation.Context implementationContext,
TypePool typePool,
FieldList<FieldDescription.InDefinedShape> fields,
MethodList<?> methods,
int writerFlags,
int readerFlags) {
Map<String, FieldDescription.InDefinedShape> mappedFields = new HashMap<String, FieldDescription.InDefinedShape>();
for (FieldDescription.InDefinedShape fieldDescription : fields) {
mappedFields.put(fieldDescription.getInternalName() + fieldDescription.getDescriptor(), fieldDescription);
}
Map<String, MethodDescription> mappedMethods = new HashMap<String, MethodDescription>();
for (MethodDescription methodDescription : CompoundList.<MethodDescription>of(methods, new MethodDescription.Latent.TypeInitializer(instrumentedType))) {
mappedMethods.put(methodDescription.getInternalName() + methodDescription.getDescriptor(), methodDescription);
}
return new MemberRemovingClassVisitor(classVisitor, fieldMatcher, methodMatcher, mappedFields, mappedMethods);
}
@Test
public void testBytecodeEnhancement() throws IOException, ClassNotFoundException {
assertFalse(isEnhanced(Address.class));
ClassReader classReader = new ClassReader(TEST_CLASSNAME);
ClassWriter writer = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
ClassVisitor visitor = writer;
HibernateEntityEnhancer hibernateEntityEnhancer = new HibernateEntityEnhancer();
visitor = hibernateEntityEnhancer.apply(TEST_CLASSNAME, visitor);
classReader.accept(visitor, 0);
final byte[] modifiedBytecode = writer.toByteArray();
TestClassLoader cl = new TestClassLoader(getClass().getClassLoader());
cl.write(TEST_CLASSNAME, modifiedBytecode);
final Class<?> modifiedClass = cl.loadClass(TEST_CLASSNAME);
assertTrue(isEnhanced(modifiedClass));
}
public static void checkClass(Class<?> cls, OptionDescriptor option, Set<Class<?>> checked, Classpath cp) throws IOException {
if (!checked.contains(cls)) {
checked.add(cls);
Class<?> superclass = cls.getSuperclass();
if (superclass != null && !superclass.equals(Object.class)) {
checkClass(superclass, option, checked, cp);
}
String classFilePath = cls.getName().replace('.', '/') + ".class";
ClassReader cr = new ClassReader(Objects.requireNonNull(cp.getInputStream(classFilePath), "Could not find class file for " + cls.getName()));
ClassVisitor cv = new OptionsVerifier(cls, option);
cr.accept(cv, 0);
}
}
@Override
public Void visitExecutable(ExecutableElement e, ClassVisitor visitor) {
if (e.getModifiers().contains(Modifier.PRIVATE)) {
return null;
}
String[] exceptions =
e.getThrownTypes().stream()
.map(descriptorFactory::getInternalName)
.toArray(count -> new String[count]);
MethodVisitor methodVisitor =
visitor.visitMethod(
accessFlagsUtils.getAccessFlags(e),
e.getSimpleName().toString(),
descriptorFactory.getDescriptor(e),
signatureFactory.getSignature(e),
exceptions);
if (methodVisitor != null) {
visitParameters(e.getParameters(), methodVisitor, MoreElements.isInnerClassConstructor(e));
visitDefaultValue(e, methodVisitor);
visitAnnotations(e, methodVisitor::visitAnnotation);
methodVisitor.visitEnd();
}
return null;
}
private Set<String> visitClass(String className, Map<String, byte[]> classMap) {
DependencyCollector dependencyCollector = new DependencyCollector();
ClassReader reader = new ClassReader(classMap.get(className));
SignatureVisitor signatureVisitor = new SignatureDependencyVisitor(dependencyCollector);
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
ClassVisitor classVisitor = new ClassDependencyVisitor(signatureVisitor, dependencyCollector, writer, preserveDebugInfo);
reader.accept(classVisitor, 0);
classMap.put(className, writer.toByteArray());
return dependencyCollector.getDependencies();
}
public MethodInstReplacer(ClassVisitor classVisitor, String methodName,
String targetClassName, String targetMethodName,
String delegateClassName, String delegateMethodName) {
super(ASMVersion.VERSION, classVisitor);
this.methodName = Assert.requireNonNull(methodName, "methodName");
this.targetClassName = Assert.requireNonNull(targetClassName, "targetClassName");
this.targetMethodName = Assert.requireNonNull(targetMethodName, "targetMethodName");
this.delegateClassName = Assert.requireNonNull(delegateClassName, "delegateClassName");
this.delegateMethodName = Assert.requireNonNull(delegateMethodName, "delegateMethodName");
}
@Override
public byte[] transform(String name, String transformedName,
byte[] basicClass)
{
if(!visitors.containsKey(transformedName))
return basicClass;
System.out.println(
"Transforming " + transformedName + ", obfuscated=" + obfuscated);
try
{
ClassReader reader = new ClassReader(basicClass);
ClassWriter writer = new ClassWriter(
ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
ClassVisitor visitor = visitors.get(transformedName)
.getConstructor(ClassVisitor.class, boolean.class)
.newInstance(writer, obfuscated);
reader.accept(visitor, 0);
return writer.toByteArray();
}catch(Exception e)
{
e.printStackTrace();
return basicClass;
}
}
private void analyzeClass(final String className, ClassResult classResult) {
try {
final ClassReader classReader = new ContextClassReader(className);
final ClassVisitor visitor = new JAXRSClassVisitor(classResult);
classReader.accept(visitor, ClassReader.EXPAND_FRAMES);
} catch (IOException e) {
LogProvider.error("The class " + className + " could not be loaded!");
LogProvider.debug(e);
}
}
@Override
public void begin(final String name, final Attributes attrs) {
String desc = attrs.getValue("desc");
boolean visible = Boolean.valueOf(attrs.getValue("visible")).booleanValue();
Object v = peek();
if (v instanceof ClassVisitor) {
push(((ClassVisitor) v).visitAnnotation(desc, visible));
} else if (v instanceof FieldVisitor) {
push(((FieldVisitor) v).visitAnnotation(desc, visible));
} else if (v instanceof MethodVisitor) {
push(((MethodVisitor) v).visitAnnotation(desc, visible));
}
}
TypeHierarchyClassVisitor(
int api,
String resourcePath,
TypeHierarchyBuilder typeHierarchyBuilder,
ClassVisitor classVisitor) {
super(api, classVisitor);
this.resourcePath = resourcePath;
this.typeHierarchyBuilder = typeHierarchyBuilder;
}
/**
* Makes the given class visitor visit this method.
*
* @param cv
* a class visitor.
*/
public void accept(final ClassVisitor cv) {
String[] exceptions = new String[this.exceptions.size()];
this.exceptions.toArray(exceptions);
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
if (mv != null) {
accept(mv);
}
}
protected AllocateInstrument(ClassVisitor cv,
TreeMap<String, Integer> methodToLargestLocal,
Properties options, Properties state,
String excludeList,
boolean logPointerChange) {
super(cv, methodToLargestLocal, options, state);
this.logPointerChange = logPointerChange;
// always add the instrument package to the exclude list
excludePackages.add(INSTRUMENT_PACKAGE);
if (excludeList != null) {
String[] packageList = excludeList.split(";");
for (String p : packageList) {
p = p.replace('.', '/');
if (!p.endsWith("/"))
p += p + "/";
excludePackages.add(p);
}
}
String path = options.getProperty(PROP_AGENT_DIRECTORY);
if (path!=null) {
File agentPath = new File(path);
File log = new File(agentPath,ALLOCATE_BASE_LOG_FILE_NAME);
if (agentPath.exists() && agentPath.canWrite()) {
if (!log.exists() || (log.exists() && log.canWrite()))
this.allocateLogBaseName = log.getAbsolutePath();
}
}
}
@Test
public void testVisitMethodNotToIntercept() {
ClassVisitor cv = mock(ClassVisitor.class);
ServletContextAdapter sca = new ServletContextAdapter(cv);
MethodVisitor result = sca.visitMethod(ACC_PUBLIC, "addListeners", "(Ljava/lang/Object;)V", null, null);
assertThat(result, not(instanceOf(EnahceAddListener.class)));
result = sca.visitMethod(ACC_PUBLIC, "addListener", "(Ljava/util/List;)V", null, null);
assertThat(result, not(instanceOf(EnahceAddListener.class)));
result = sca.visitMethod(ACC_PUBLIC, "addListener", "(Ljava/lang/String;)V", null, null);
assertThat(result, not(instanceOf(EnahceAddListener.class)));
}
/**
* Generate the constructor for the subclass, the ctor simply calls the
* superclass ctor and does nothing else besides
*
* @param ref Class ref being generated
* @param desc Argument descriptor
* @param args Parsed argument list from descriptor
* @param writer Class writer
*/
private void generateCtor(ArgsClassInfo info, ClassVisitor writer) {
MethodVisitor ctor = writer.visitMethod(Opcodes.ACC_PRIVATE, Constants.CTOR, ArgsClassGenerator.CTOR_DESC, null, null);
ctor.visitCode();
ctor.visitVarInsn(Opcodes.ALOAD, 0);
ctor.visitVarInsn(Opcodes.ALOAD, 1);
ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, ArgsClassGenerator.ARGS_REF, Constants.CTOR, ArgsClassGenerator.CTOR_DESC, false);
ctor.visitInsn(Opcodes.RETURN);
ctor.visitMaxs(2, 2);
ctor.visitEnd();
}
public void analyze(OutputStream out) {
for (Map.Entry<String, byte[]> e : classBytes.entrySet()) {
ClassReader reader = new ClassReader(e.getValue());
ClassVisitor visitor = new CheckClassAdapter(new TraceClassVisitor(new PrintWriter(out, true)));
reader.accept(visitor, 0);
}
}
BackportingTypeRemapper(ClassVisitor cv) {
super(ASM5, cv, new Remapper() {
@Override public String map(String type) {
String remap = TYPES.get(type);
if (remap != null) {
System.out.println(" Mapping type " + type + " to " + remap);
return remap;
}
return type;
}
});
}
@Override
public ClassVisitor apply(String className, ClassVisitor outputClassVisitor) {
return new PanacheJpaRepositoryClassVisitor(className, outputClassVisitor, panacheRepositoryBaseClassInfo,
this.indexView);
}
public ClassPatcher(ClassVisitor visitor) {
super(ASM5, visitor);
}
public IncludingClassVisitor(ClassVisitor cv) {
super(Opcodes.ASM5, cv);
}
public ClassPatcher(ClassVisitor visitor) {
super(ASM5, visitor);
}
public RenameClassVisistor(ClassVisitor cw) {
super(Opcodes.ASM5, cw);
}
@Override
public Void visitType(TypeElement e, ClassVisitor visitor) {
if (classVisitorStarted) {
// We'll get inner class references later
return null;
}
TypeMirror superclass = e.getSuperclass();
if (superclass.getKind() == TypeKind.NONE) {
superclass = Objects.requireNonNull(elements.getTypeElement("java.lang.Object")).asType();
}
int classFileVersion = SourceVersionUtils.sourceVersionToClassFileVersion(targetVersion);
visitor.visit(
classFileVersion,
accessFlagsUtils.getAccessFlagsForClassNode(e),
descriptorFactory.getInternalName(e),
signatureFactory.getSignature(e),
descriptorFactory.getInternalName(superclass),
e.getInterfaces().stream()
.map(descriptorFactory::getInternalName)
.toArray(size -> new String[size]));
classVisitorStarted = true;
// Handle nests in Java 11+. See JEP 181 (https://openjdk.java.net/jeps/181) for details.
if (classFileVersion >= Opcodes.V11) {
if (e.getNestingKind().isNested()) {
visitNestHost(e, visitor);
} else {
visitNestMembers(e, visitor);
}
}
visitAnnotations(e, visitor::visitAnnotation);
super.visitType(e, visitor);
InnerClassesTable innerClassesTable =
new InnerClassesTable(descriptorFactory, accessFlagsUtils, e);
if (e.getKind().isClass() || classFileVersion >= Opcodes.V1_8) {
try {
generateBridges(e, visitor, innerClassesTable);
} catch (UnsupportedOperationException | CannotInferException ex) { // NOPMD
// Can't generate bridges in source-only mode
}
}
innerClassesTable.reportInnerClassReferences(visitor);
return null;
}
@Override
public void init(final AsmClassGenerator asmClassGenerator, final GeneratorContext gcon, final ClassVisitor cv, final ClassNode cn) {
delegationController.init(asmClassGenerator, gcon, cv, cn);
}
public ClassPatcher(ClassVisitor visitor) {
super(ASM5, visitor);
}