위의 예시에서, 바이트 코드 조작부와 조작 대상의 클래스를 사용하는 부분 new Moja().pullOut() 을 동시에 사용할 수 없었다. 이유는, 바이트 코드 조작부에 의하여 빌드된 target 내 Moja.class 는 조작되겠지만, 그 전에 클래스 로더에 의해 조작되기 전 Moja.class 가 메모리에 먼저 올라가기 때문이다. 즉, new Moja().pullOut() 는 메모리에 이미 올라온, 조작되기 전 Moja.class 를 사용하게 된다.
따라서 조작부를 클래스로더가 프로젝트 내 클래스들을 읽기 전에 먼저 실행되게할 필요가 있는데, 이러한 방법 중 하나로 Agent 를 사용할 수 있다. Agent 는 java 에서 지원하는 스펙 중 하나로, 실행 과정에서 클래스 로더에 거치기 전에 Agent 가 먼저 실행된다. 즉 이 Agent 에 바이트 코드 조작부를 넣으면 클래스 로더는 조작된 Moja.class 를 읽게 되는 것이다.
바이트코드 조작
자바는 .java 를 컴파일해서 .class파일을 만든다
.class파일을 보고 바이트 코드라고 한다
컴파일한뒤에 클래스로더가 class파일을 jvm의 메모리에 올린다 그리고 사용하는 순서이다
그런데 이 과정에서 컴파일된 파일을 수정한다면 어떻게 될까?
나의 파일은 a를 출력하라고하지만 내가 컴파일된파일을 수정하여 b를 출력하라고 한다면
b를 출력하게 할 수 있다.
근데 바이트코드조작을 사용할때 유의 해야할점이 있는데 코드 순서는
1. 바이트 코드 조작
2. 조작된 코드에 대한 메서드 호출
이겠지만 실제로는 바이트코드가 조작되기 전에 클래스가 메모리에로드된다
그리고 바이트 코드는 target하위에 있는 class파일을 조작한다
나는 메모리에 로드된것을 사용하기 때문에 조작된 파일에 대한 메서드출력내용이 보이지 않는다
그래서 2번을 주석해제하고 1번을 실행한 뒤에 2번만 따로 실행해야 그게 가능해진다.
지금 이 상황에서의 문제는 로드가 먼저 된다음에 target하위에있는 클래스를 조작한다는 점이다.
조작을 한 다음에 그 조작한 class파일을 로드해야한다.
이를가능하게 하는게 agent다