简体   繁体   English

使用ASM的Java字节码检测,MethodVisitor为空

[英]Java bytecode instrumentation using ASM, MethodVisitor is null

So, with the code written below, my output is: 因此,使用下面的代码,我的输出是:

Starting application with the Agent
Visiting class: HelloWorld
Class Major Version: 51
Super class: java/lang/Object
Source: HelloWorld.java
Method: <init> desc = ()V cv = com.amir.agent.instrumentor.amirClassVisitor$1@79f1d448 and mv = null
Method: main desc = ([Ljava/lang/String;)V cv = com.amir.agent.instrumentor.amirClassVisitor$1@79f1d448 and mv = null
Method: foo desc = ()V cv = com.amir.agent.instrumentor.amirClassVisitor$1@79f1d448 and mv = null
Method ends here
Done instrumenting: HelloWorld

which is puzzling me. 这让我感到困惑。 Why would my methodVisitor be null ? 为什么我的methodVisitornull The ASM source code seems to only return null for the methodVisitor when the classVisitor is null , which is not true in my case. classVisitornull ,ASM源代码似乎仅对methodVisitor返回null ,在我的情况下不正确。

package com.amir.agent.instrumentor;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class amirClassVisitor {

    private byte[] outData = null;

    public amirClassVisitor() {
    }

    public void performInstrumentation(final String className,
                                       final byte[] classAsBytes) {
        final ClassVisitor cl = new ClassVisitor(Opcodes.ASM4) {
            @Override
            public void visit(final int version,
                              final int access,
                              final String name,
                              final String signature,
                              final String superName,
                              final String[] interfaces) {
                System.out.println("Visiting class: "+name);
                System.out.println("Class Major Version: "+version);
                System.out.println("Super class: " + superName);
                super.visit(version, access, name, signature, superName, interfaces);
            }

            @Override
            public void visitOuterClass(final String owner,
                                        final String name,
                                        final String desc) {
                System.out.println("Outer class: "+owner);
                super.visitOuterClass(owner, name, desc);
            }

            @Override
            public AnnotationVisitor visitAnnotation(final String desc,
                                                     final boolean visible) {
                System.out.println("Annotation: "+desc);
                return super.visitAnnotation(desc, visible);
            }

            @Override
            public void visitAttribute(final Attribute attr) {
                System.out.println("Class Attribute: " + attr.type);
                super.visitAttribute(attr);
            }

            @Override
            public void visitInnerClass(final String name,
                                        final String outerName,
                                        final String innerName,
                                        final int access) {
                System.out.println("Inner Class: " + innerName + " defined in " + outerName);
                super.visitInnerClass(name, outerName, innerName, access);
            }

            @Override
            public FieldVisitor visitField(final int access,
                                           final String name,
                                           final String desc,
                                           final String signature,
                                           final Object value) {
                System.out.println("Field: "+name+" "+desc+" value:"+value);
                return super.visitField(access, name, desc, signature, value);
            }

            @Override
            public void visitEnd() {
                System.out.println("Method ends here");
                super.visitEnd();
            }

            @Override
            public MethodVisitor visitMethod(final int access,
                                             final String name,
                                             final String desc,
                                             final String signature,
                                             final String[] exceptions) {
                final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
                System.out.println("Method: " +name+ " desc = " +desc+ " cv = " +this+ " and mv = " +mv);
                return mv;
            }

            @Override
            public void visitSource(final String source,
                                    final String debug) {
                System.out.println("Source: "+source);
                super.visitSource(source, debug);
            }

        };

        final ClassReader classReader = new ClassReader(classAsBytes);
        classReader.accept(cl, 0);
        System.out.println("Done instrumenting: " +className);

    }

    public byte[] result() {
        return outData;
    }

}

EDIT: 编辑:

I call this code like this: 我将这样的代码称为:

public class ClassLoadInterceptor implements ClassFileTransformer {

    @SuppressWarnings("unchecked")
    public byte[] transform(final java.lang.ClassLoader loader,
                            final java.lang.String className,
                            final java.lang.Class classBeingRedefined,
                            final java.security.ProtectionDomain protectionDomain,
                            final byte[] classfileBuffer) throws IllegalClassFormatException {

        if (!(className.startsWith("java") || className.startsWith("sun") || className.startsWith("com/workday/agent"))) {
            WorkdayClassVisitor v = new WorkdayClassVisitor();
            v.performInstrumentation(className, classfileBuffer);
            System.out.println("\t Instrumenting : " +className);
            byte[] instrumented_class = v.result();
            writeOutClassFile("debug", className + ".class", classfileBuffer);
            writeOutClassFile("debug", className + "_instrumented" + ".class", instrumented_class);
            return instrumented_class;
        }

        return classfileBuffer;

    }

What you print out is not “my methodVisitor ” but the value returned by the super invocation of visitMethod , in other words the default value returned by ClassVisitor.visitMethod : 你打印出来是不是“我的methodVisitor ”,但被返回的值super的调用visitMethod ,换句话说返回的默认值ClassVisitor.visitMethod

Returns : 返回值
an object to visit the byte code of the method, or null if this class visitor is not interested in visiting the code of this method. 一个对象,用于访问方法的字节码;如果该类访问者对访问此方法的代码不感兴趣,则返回null

Since the abstract class ClassVisitor does not implement any action, it has no interest in visiting the method and therefore null is the perfect return value. 由于抽象类ClassVisitor不执行任何操作,因此对访问该方法没有兴趣,因此null是理想的返回值。

So it's up to you, to instantiate a new MethodVisitor implementing your desired behavior. 因此,由您决定实例化一个新的MethodVisitor实现所需的行为。 Or, since you seem to intend to instrument a class, let your class visitor delegate to a ClassWriter which you pass to the super class constructor . 或者,由于您似乎打算插入一个类,因此让您的类访问者委托给您传递给超类构造函数ClassWriter This way you will inherit a replication behavior that you can customize. 这样,您将继承可以自定义的复制行为。 Then, super.visitMethod will return a non- null method visitor, which will replicate the method. 然后, super.visitMethod将返回一个非null方法访问者,该访问者将复制该方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用ASM的Java中的字节码检测系统类 - Bytecode instrumentation system classes in Java with ASM 使用ASM的Java字节码检测:在INVOKESPECIAL指令处对代码注入进行VerifyError - Java Bytecode instrumentation with ASM: VerifyError on code injection at INVOKESPECIAL instructions 使用ASM字节码检测在堆栈上加载构造函数参数(值) - Load constructor argument (values) on stack using ASM bytecode instrumentation Java ASM MethodVisitor的方法未由ClassVisitor调用 - Java ASM MethodVisitor's methods are not called by ClassVisitor Java字节码检测的替代方案 - Alternatives to Java bytecode instrumentation 本机java字节码检测 - native java bytecode instrumentation 与ASM字节码检测功能不兼容的参数 - Incompatible argument to function with ASM bytecode instrumentation 如何使用 ASM 4.0 修改 Java 字节码 - How to modify a Java bytecode using ASM 4.0 我正在尝试学习用于字节码检测的Java ASM框架,但无法在其上找到足够的文档或教程 - I am trying to learn java asm framework for bytecode instrumentation but not able to find sufficient docs or tutorials on it 使用asm完成字节码检测后,将引发java.lang.reflect.InvocationTargetException。 - java.lang.reflect.InvocationTargetException gets thrown when bytecode instrumentation is finished with asm.
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM