Java

[Java] JavaAgent

딸기케잌🍓 2021. 1. 17. 21:28

JavaAgent 란?

JVM 에서 동작하는 Java 어플리케이션으로 JVM의 다양한 이벤트를 전달받거나 바이트코드 제어 등을 특정 API를 통하여 수행할 수 있습니다.

또한 JavaAgent는 JDK1.5부터 제공하는 자바 instrumentation API로 소스코드의 변경없이 런타임 중에 자바 바이트 코드를 변조할 수 있게 하는 강력한 기능을 제공합니다.

 

자바 코드는 결국 바이트 코드로 변환이 된 후에 JVM이 바이트 코드를 읽어 실행이 됩니다.

즉 최종적으로 바이트 코드 내용으로 실행이 되기 때문에 바이트 코드를 조작한다면, 개발자가 최초로 작성한 코드와 다른 결과가 나올 수 있습니다.
Java agent가 클래스파일을 직접 바꾸는 것이 아닌, 실행 후 JVM에 클래스로딩이 이루어지는 시점에 동작하기 때문에 외부에서 봤을때 변경 내용이 확인되지는 않습니다.

말그대로 특정 임무를 몰래 수행하는 비밀 요원같은 느낌이네요. ^>^

 

Java agnet와 instrumentation API는 java.lang.instrument 패키지에서 찾아 볼 수 있습니다.

 

 

JavaAgent의 구동 방법은?

agent는 JAR 파일의 형태로 배포되고 JAR 파일의 manifest 파일에서 로드될 agent의 시작점(premain 클래스)을 명시해야 합니다.

-javaagnet:jarpath[=options]

Java application을 구동시킬 때 위와 같은 명령어로 jar파일(agent파일)을 추가해줄 수 있습니다.

jarpth : jar 파일의 경로를 뜻합니다.

options : agent의 옵션입니다.

 

 

예시)

-javaagent:/sw/jar/myagent.jar=output=tcpserver,includes=*.*,address=1.1.1.1,port=8088
,append=false Myapp.war

Myapp.war 파일을 구동시키는데 /sw/jar 경로에 있는 myagent.jar라는 javaAgent를 추가하여 구동시키는 예시입니다.

'output=tcpserver...append=false'는 myagent.jar라는 javaAgent에서 자체적으로 사용하는 옵션입니다.

 

 

 

Premain 메서드

Premain 메서드는 application의 main 메서드가 시작하기 전에 먼저 실행되는 메서드입니다.

JVM이 구동된 이후 agent가 명시된 순서대로 각각의 Premain클래스가 불려집니다. 그 후 application의 main 함수가 불려집니다. 각각의 premain메소드는 시작된 순서대로 리턴 되어야 합니다.

public static void premain(String agentArgs, Instrumentation inst); -------(1)
public static void premain(String agentArgs); -----------------------------(2)

premain 메서드의 형태는 위와 같습니다.

 


JVM은 premain 메서드의 (1) 형태의 premain 메서드부터 호출하길 시도하고 이와 같은 형태가 없다면 

(2) 형태의 premain 메서드를 호출합니다.

 

agent class는 시스템 클래스 로더에 의해 로드됩니다. 

시스템 클래스 로더는 일반적으로 애펄르케이션 메인 메서드를 포함한 클래스를 로드하는 로더 입니다.

스레드 생성을 포함하여 애플리케이션의 main 메서드에서 수행 할 수있는 모든 작업은 premain에서도 가능합니다.

에이전트를 확인할 수없는 경우 (예를들어 에이전트 클래스를로드 할 수 없거나 에이전트 클래스에 적절한 premain 메서드가 없는 경우) JVM이 중단됩니다. 

 

Agent 옵션

agentArgs 파라미터를 이용하여 agent는 자신이 필요한 옵션들을 전달받을 수 있습니다.  agent 옵션은 하나의 문자열으로 전달되고 agnet 안에서 옵션을 파싱하여 사용할 수 있습니다.

 

 

JavaAgent가 런타임에 클래스를 변조하는 원리

  1. Java Agent는 premain이라는 메소드를 구현합니다.JVM은 Java Agent의 premain 메소드를 호출해서 Agent를 구동한 후에 Application의 main 메소드를 호출합니다.
  2. Java Agent는 ClassFileTransformer (클래스파일 변환기) 인터페이스를 구현하고, Instrumentation.addTransformer를     이용해서 클래스 파일 변환기를 JVM에 등록합니다.
  3. JVM은 클래스 파일을 로드할 때 등록된 ClassFileTransformer의 transform 메소드를 호출해서 클래스파일의 바이트 코드를  변환합니다. 변환된 바이트 코드를 원래 클래스 대신 사용합니다. 바이트 코드를 변환하기 위해서 ASM라이브러리를 사용합니다.
  4. Agent는 필요한 시점에 Instrumentation.redefineClasses 메소드를 이용해 특정 클래스의 바이트 코드를 런타임에 변경합니다.






참고사이트

www.developer.com/java/data/what-is-java-agent.html

 

What Is Java Agent? | Developer.com

Java agents work at the lowest level by providing services that enable us to intrude into a running Java program in JVM. This powerful yet uncanny part of

www.developer.com

docs.oracle.com/javase/9/docs/api/java/lang/instrument/package-summary.html

'Java' 카테고리의 다른 글

[Java] 컴파일러 vs 인터프리터 vs JIT compiler  (0) 2021.05.31
[Java] JVM 구조와 원리  (0) 2021.05.23
[Java] Static 변수, static 메소드  (0) 2021.05.23
[Java] String, StringBuffer, StringBuilder  (0) 2021.04.22
[Java] Garbage Collector  (0) 2020.05.11