바이트코드 조작 라이브러리
- 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());
}
}
- 빈 문자열을 리턴하므로 빈 문자열이 출력됩니다.
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가 로딩이 되어버리기 때문입니다.
- 실행하면 콘솔창에 아무일도 일어나지 않습니다.
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());
}
}
- 바이트코드를 조작했기 때문에 "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 |
댓글