簡體   English   中英

使用ASM的Java字節碼檢測,MethodVisitor為空

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

因此,使用下面的代碼,我的輸出是:

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

這讓我感到困惑。 為什么我的methodVisitornull 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;
    }

}

編輯:

我將這樣的代碼稱為:

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;

    }

你打印出來是不是“我的methodVisitor ”,但被返回的值super的調用visitMethod ,換句話說返回的默認值ClassVisitor.visitMethod

返回值
一個對象,用於訪問方法的字節碼;如果該類訪問者對訪問此方法的代碼不感興趣,則返回null

由於抽象類ClassVisitor不執行任何操作,因此對訪問該方法沒有興趣,因此null是理想的返回值。

因此,由您決定實例化一個新的MethodVisitor實現所需的行為。 或者,由於您似乎打算插入一個類,因此讓您的類訪問者委托給您傳遞給超類構造函數ClassWriter 這樣,您將繼承可以自定義的復制行為。 然后, super.visitMethod將返回一個非null方法訪問者,該訪問者將復制該方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM