본문 바로가기

Java/Java

(JAVA) 바이트코드 조작(3) - javaagent

bytebuddy 문서 참조

응용 프로그램이 커지고 모듈화 될 때 특정 프로그램 지점에서 이러한 변경사항을 적용하는 것은 제약이 많이 따릅니다. 

그리고 그러한 클래스를 재정의할 때 적용 할 수있는 더 좋은 방법이 있습니다 . Javaagent 사용하면 Java 응용 프로그램 내에서 수행되는 모든 클래스 로딩 활동을 직접 가로 챌 수 있습니다. Java 에이전트는 링크 된 자원에 설명 된대로이 jar 파일의 Manifest 파일에 지정된 시작점이 있는 단순 jar 파일로 구현됩니다 . 바이트 버디를 사용하면 이러한 에이전트의 구현을 간단하게 사용할 수 있습니다.


새로운 프로젝트 생성

  • 위의 코드를 참조하여 동일하게 생성
public class MasulaAgent {

    public static void premain(String agentArgs, Instrumentation inst) {
        new AgentBuilder.Default()
                .type(ElementMatchers.any())
                .transform(new AgentBuilder.Transformer() {
                    @Override
                    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) {
                        return builder.method(named("PullOut")).intercept(FixedValue.value("Rabbit!"));
                    }
                }).installOn(inst);

    }
}

 

  • agent를 jar로 패키징

https://maven.apache.org/plugins/maven-jar-plugin/examples/manifest-customization.html

 

Apache Maven JAR Plugin – Manifest customization

Customization the Manifest The default manifest can be altered with the archive configuration element. Below you will find some of the configuration options that are available. For more info see the Maven Archiver reference. ... org.apache.maven.plugins ma

maven.apache.org

 

https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html

 

java.lang.instrument (Java Platform SE 8 )

Package java.lang.instrument Description Provides services that allow Java programming language agents to instrument programs running on the JVM. The mechanism for instrumentation is modification of the byte-codes of methods. Package Specification An agent

docs.oracle.com

 

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.1.2</version>
        <configuration>
          <archive>
            <index>true</index>
            <manifest>
              <addClasspath>true</addClasspath>
            </manifest>
            <manifestEntries>
              <mode>development</mode>
              <url>${project.url}</url>
              <key>value</key>
              <Premain-Class>me.choi.MasulaAgent</Premain-Class>
              <Can-Redefine-Classes>true</Can-Redefine-Classes>
              <Can-Retransform-Classes>true</Can-Retransform-Classes>
            </manifestEntries>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

Premain-Class, Can-Redefind-Classes, Can-Retransform-Classes 추가

 

Agent 패키징 실행

mvn clean package

maven 패키징
target에 jar 파일 생성된 것 확인

 

해당 파일을 열어보면 내가 설정한대로 설정되어있는 것을 확인 할 수 있다.


본 프로젝트에 돌아와서 작성한 jar파일을 불러와보자

VM options에 해당 javaaagent 경로 삽입

-javaagent:/Applications/개발환경/repository/PURE_JAVA/TheJava/MasulsaAgent/target/MasulsaAgent-1.0-SNAPSHOT.jar 

 

출력

정말 코드에 아무 짓도 하지 않았다.

public class Masulsa {

    public static void main(String[] args) throws IOException {

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

 

실행결과

헐! 토끼가 들어있네!?!

바이트코드를 살펴보자

바이트 코드도 변형되지 않았다....

클래스 파일 자체를 변경하는 것이 아니라

클래스 로딩할 때 javaagent를 거쳐서 변경된 바이트코드를 적용된다.

이 당시에 변경된 바이트코드를 읽어서 메모리에 할당한다.


Code Link

https://github.com/mike6321/PURE_JAVA/tree/master/TheJava

 

mike6321/PURE_JAVA

Contribute to mike6321/PURE_JAVA development by creating an account on GitHub.

github.com