본문 바로가기
Java

바이트코드 조작 라이브러리

by 박성민 2021. 10. 27.

바이트코드 조작 라이브러리

  • ASM
  • Javassist
  • ByteBuddy

바이트코드 조작해보기

모자에서 토끼를 꺼내는 마술

Moja.java

public class Moja {

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

Masulsa.java

public class Masulsa {

    public static void main(String[] args) {
        System.out.println(new Moja().pullOut());
    }
}

1

  • 빈 문자열을 리턴하므로 빈 문자열이 출력됩니다.

Byte Buddy 의존성 추가

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

Masulsa 클래스에 코드 추가

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.FixedValue;

import java.io.File;
import java.io.IOException;

import static net.bytebuddy.matcher.ElementMatchers.named;

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("C:\\workspace_sts\\classloadersample\\target\\classes\\"));
        } catch (IOException e) {
            e.printStackTrace();
        }

//        System.out.println(new Moja().pullOut());
    }
}
  • redefine
    • 어떤 클래스를 재정의한다는 메서드입니다.
  • .method(named("pullOut")).intercept(FixedValue.value("Rabbit!"))
    • "pullOut"이라는 메서드를 가로채서 "Rabbit!" 이라는 값을 리턴하게 한다는 의미입니다.
  • .make().saveIn(new File("C:\workspace_sts\classloadersample\target\classes\"));
    • 설정한 내용을 저장하는 코드입니다.
    • saveIn은 폴더를 지정하는 메서드입니다.
  • 이 때 콘솔 출력 코드와 함께 실행하면 안됩니다.
    • main이 실행되기 전에 클래스 로딩 시 Moja가 로딩이 되어버리기 때문입니다.

2

  • 실행하면 콘솔창에 아무일도 일어나지 않습니다.

main 코드 변경 후 실행

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.FixedValue;

import java.io.File;
import java.io.IOException;

import static net.bytebuddy.matcher.ElementMatchers.named;

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("C:\\workspace_sts\\classloadersample\\target\\classes\\"));
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

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

3

  • 바이트코드를 조작했기 때문에 "Rabbit!"이 출력됩니다.
public class Moja {

    public String pullOut() {
        return "";
    }
}
  • java 소스 코드는 변함이 없습니다.
public class Moja {
    public Moja() {
    }

    public String pullOut() {
        return "Rabbit!";
    }
}
  • 실제 class 파일에는 "Rabbit!"이 추가됩니다.

참조

'Java' 카테고리의 다른 글

바이트코드 조작 정리  (0) 2021.10.30
javaagent 사용해보기  (0) 2021.10.28
코드 커버리지 측정하는 방법  (0) 2021.10.27
클래스 로더  (0) 2021.10.26
JVM 구조  (0) 2021.10.26

댓글