반응형

메이븐 Bytebuddy 설정

  <dependency>
    <groupId>net.bytebuddy</groupId>
    <artifactId>byte-buddy</artifactId>
    <version>1.11.0</version>
  </dependency>

 

Moja.java

public class Moja {
    public String pullOut() {
        return "";
    }
}

Moja.class 바이트 코드 조작하기

public class Masulsa {
    public static void main(String[] args) {
        try {
            new ByteBuddy().redefine(Moja.class)
                    .method(named("pullOut")).intercept(FixedValue.value("Rabbit!"))
                    .make().saveIn(new File("F:\\classloader-sample\\target\\classes\\"));
        } catch (IOException e) {
            e.printStackTrace();
        }

//        System.out.println(new Moja().pullOut());
    }
}

기존 Moja.class

public class Moja {
    public Moja() {
    }

    public String pullOut() {
        return "";
    }
}

조작된 Moja.class

public class Moja {
    public Moja() {
    }

    public String pullOut() {
        return "Rabbit!";
    }
}

 

  • Bytebuddy를 이용해서 Moja.class를 재정의한다.
  • Moja에 있는 pullOut 메소드를 가로채서 고정된 값인 Rabbit!을 출력하도록 설정하고 클래스 파일이 존재하는 폴더 위치를 지정해주면 해당 코드 실행 시 바이트 코드가 변경이 된다.
  • System.out.println과 동시에 사용하면 바이트코드 조작이 먹히지 않는다. 그 이유는 실행을 하게 되면, Masulsa.class, Moja.class로 컴파일되고 클래스로딩 과정에서 메소드 영역에 해당 클래스와 메소드와 관련된 정보들이 저장된다. 그 이후에 Bytebuddy통해서 Moja.class 파일을 조작한다고해도 이미 로딩된 클래스 정보(메소드 영역에 있는)를 보고 값을 출력하고있기 때문에 Rabbit!이 표시되지않는다.
  • 처음 실행할때는 위와 같은 이유로 Rabbit! 문구가 표시가 되지않지만 두 번째 실행부터는 별도로 Moja.java 파일을 다시 컴파일 하지 않는다면 Bytebuddy가 Moja.class 파일을 조작한 상태이기 때문에 Rabbit! 문구가 표시된다.
반응형

+ Recent posts