(Instrument API, Agent)My ClassFileTransformer's transform method fails to recognize a specific class in Springboot

38 Views Asked by At

Background: Hello, I am developing an Agent through bytecode manipulation. Using the Instrument API, I aimed to read all classes before class loading by utilizing premain - ClassFileTransformer. My goal was to compare a specific class in Springboot using "className.contains" for string comparison.

Issue at hand: I cannot read a specific class file 'Chap03' belonging to the Springboot main during the transformation process. Despite logging and reading all the class names loaded in transform, that particular class was not found.

What's peculiar is that the class 'Chap03' can be found in transform when adding annotations like @Configuration that trigger context scanning. I am at a loss for the cause and seek advice.

As an attempt to resolve the issue, I forcibly inserted code in premain like 'Class.forName("com.dummy.jdbcserver.example_asm.Chap03");' to read the class, but it was not recognized."

and here is my code:

  1. premain
package org.agent;

import org.agent.util.init.*;
import org.agent.util.transform.Chap03Transformer;
import org.agent.util.transform.MyClassTransformer;

import java.lang.instrument.Instrumentation;


public class MyAgent {

    public static void premain(String agentArgs, Instrumentation instrumentation)  {

        Banner.send(agentArgs); //로그 찍기
        ConfigRead configRead = new ConfigRead(); //Config Read
        //CallThread.run(); JMX 쓰레드 생성 및 호출


        // MyClass를 명시적으로 로드하여 transform 메서드에서 감지될 수 있게 한다.
        // Springboot에서 이상하게 @Configure 등 어노테이션이 붙지 않으면 transform 과정에서 해당 클래스를 확인할 수 없다. 이는 지연 로딩이 원인인 것으로 추정
        try {
            Class.forName("com.dummy.jdbcserver.example_asm.Chap03");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        instrumentation.addTransformer(new Chap03Transformer());

    }
}

  1. transformer
package org.agent.util.transform;

import lombok.extern.slf4j.Slf4j;
import org.agent.util.asm.AsmCodeFactory;

import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;


@Slf4j
public class Chap03Transformer implements ClassFileTransformer {


    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                            ProtectionDomain protectionDomain, byte[] classfileBuffer) {
        String containsName = "Chap03";


        if (className.contains(containsName)) {
            log.warn("[TRANSFORM] Find ClassName : {}", containsName);
            AsmCodeFactory.testCode = "SetF";
            return AsmCodeFactory.doMethod(classfileBuffer, true); //테스트 코드 실행
        }

        return classfileBuffer;
    }
}
  1. springboot class
package com.dummy.jdbcserver.example_asm;


import org.springframework.context.annotation.Configuration;

/**
 * ASM Docs 3장 예제를 위한 클래스 파일
 */
public class Chap03 {
    //It's empty, but add in bytecode file
    
    static int legacyInt; //원래 있던 변수
    
    public void legacyMethod(int a, int b) {
        //원래 있던 메서드 1
    }
}

0

There are 0 best solutions below