자바 에이전트 입문 학습 의 동적 수정 코드
최근 오후 내 내 자바 에이 전 트 를 통 과 했 습 니 다.이 글 은 잊 혀 지지 않도록 구체 적 인 조작 절 차 를 기록 하 였 습 니 다.다음은 더 이상 말 하지 않 겠 습 니 다.상세 한 소 개 를 살 펴 보 겠 습 니 다.
자바 에이전트 를 통 해 코드(교체,수정 클래스 의 정의)를 동적 으로 수정 하여 AOP 를 진행 할 수 있 습 니 다.
목표:
@ToString 주 해 를 추가 하 는 모든 클래스 에 기본 toString 방법 을 구현 합 니 다.
두 개의 프로그램 이 필요 합 니 다.하 나 는 테스트 용 프로그램 이 고,하 나 는 에이전트 가 코드 를 수정 하 는 데 사 용 됩 니 다.
1.테스트 프로그램
테스트 된 프로그램 포함:
- ToString.Java
- Foo.java
- Main.java
구체 적 인 코드 는 다음 과 같다.
ToString.java:정의 ToString 주석
package com.chosen0ne.agent.test;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface ToString {
}
Foo.java:테스트 용 으로 간단하게 ToString 주 해 를 사 용 했 습 니 다.
package com.chosen0ne.agent.test;
@ToString
public class Foo {
}
Main.java:
package com.chosen0ne.agent.test;
public class Main {
public static void main(String[] args) {
Foo foo = new Foo();
System.out.println(foo.toString());
}
}
Main.java 를 실행 한 결 과 는 다음 과 같 습 니 다.
com.chosen0ne.agent.test.Foo@7852e922
toString 이 Object 의 기본 구현 으로 돌아 오 는 것 을 볼 수 있 습 니 다.2.에이전트 프로그램
자바 에이전트 프로그램 은 실제로 갈고리 와 유사 하 며 두 가지 방식 이 있 습 니 다.
- main 함수 시작 전
- 프로그램 실행 중
여 기 는 주로 main 함수 가 시작 되 기 전의 상황 을 테스트 합 니 다.main 함수 와 유사 하여 실현 이 필요 합 니 다.
public static void premain(String agentArgs, Instrumentation inst);
이 함 수 는 main 함수 전에 호출 됩 니 다.premain 에서 바이트 코드 작업 을 하고 바 꾸 거나 클래스 를 다시 실현 할 수 있 습 니 다.이곳 은 Byte Buddy 라 이브 러 리 를 사용 하여 ASM 위 에 더욱 고 급 스 러 운 추상 을 제공 하여 사용 하기에 편리 하 다.구체 적 인 코드 는 다음 과 같다.
package com.chosen0ne.ByteCode.agent;
import java.lang.instrument.Instrumentation;
import com.chosen0ne.agent.test.ToString;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType.Builder;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.matcher.ElementMatchers;
public class ToStringAgent {
public static void premain(String args, Instrumentation instrumentation) {
System.out.println("print pre main");
new AgentBuilder.Default()
.type(ElementMatchers.isAnnotatedWith(ToString.class))
.transform(new AgentBuilder.Transformer() {
@Override
public Builder<?> transform(Builder<?> builder,
TypeDescription typeDescription, ClassLoader classLoader) {
return builder.method(ElementMatchers.named("toString"))
.intercept(FixedValue.value("test"));
}
}).installOn(instrumentation);
}
}
에이전트 는 jar 로 포장 해 야 하 며,premain 방식 에 대해 서 는 MANIFEST.MF 에서 Premain-Class 를 지정 하여 premain 함 수 를 포함 하 는 클래스 를 표시 해 야 합 니 다.구체 적 으로 포장 하 는 방법 은 두 가지 가 있다.1)jar 명령 을 직접 통과
편집 하여 MANIFEST.MF 생 성 후 실행:
jar cvfm agent.jar MANIFEST.MF -C . com lib
위 명령 으로 포 장 된 jar 포함:- com:컴 파일 생 성 된 class 파일
- lib:의존 하 는 라 이브 러 리
2)maven 을 통 해 직접 생 성:
maven-jar-plugin 플러그 인 을 통 해 jar 패 키 지 를 생 성 합 니 다.구체 적 인 설정 은 다음 과 같 습 니 다.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.1</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.chosen0ne.ByteCode.ByteBuddyTest</mainClass>
</manifest>
<manifestEntries>
<Premain-Class>com.chosen0ne.ByteCode.agent.ToStringAgent</Premain-Class>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
주로 manifestEntries 탭 을 통 해 자동 속성 을 생 성 합 니 다.여 기 는 Premain-Class 를 지정 합 니 다.3.운행
생 성 된 에이전트.jar,의존 하 는 ByteBuddy 의 jar 패키지 와 테스트 프로그램 컴 파일 로 생 성 된 class 파일 을 하나의 경로 에 놓 습 니 다.디 렉 터 리 레이아웃 은 다음 과 같 습 니 다.
.
├── agent.jar
├── classes
│ └── com
│ └── chosen0ne
│ └── agent
│ └── test
│ ├── Foo.class
│ ├── Main.class
│ └── ToString.class
└── lib
└── byte-buddy-1.2.3.jar
현재 디 렉 터 리 에서 명령 실행:
java -cp classes:lib/byte-buddy-1.2.3.jar -javaagent:agent.jar com.chosen0ne.agent.test.Main
실행 결 과 는 다음 과 같 습 니 다.
print pre main
test
테스트 프로그램 도 jar 패키지 로 포장 하면-cp 를 통 해 ByteBuddy 라 이브 러 리 를 지정 할 때 실패 합 니 다.대응 하 는 class 를 찾 을 수 없습니다.오 류 는 다음 과 같 습 니 다.
> java -cp classes:lib/byte-buddy-1.2.3.jar -javaagent:agent.jar -jar agent-test-case-0.0.1-SNAPSHOT.jar
Exception in thread "main" java.lang.NoClassDefFoundError: net/bytebuddy/matcher/ElementMatcher
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
at java.lang.Class.getDeclaredMethod(Class.java:2115)
at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:327)
at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401)
Caused by: java.lang.ClassNotFoundException: net.bytebuddy.matcher.ElementMatcher
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 5 more
FATAL ERROR in native method: processing of -javaagent failed
아직 구체 적 인 이 유 는 모 르 겠 지만...그래서 그냥 클 라 스 로 실행 하면 돼 요.총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.