Java字节码instrument研究
生活随笔
收集整理的這篇文章主要介紹了
Java字节码instrument研究
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
MyAgent項(xiàng)目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.book.MyAgent</groupId><artifactId>MyAgent</artifactId><version>1.0</version><dependencies><dependency><groupId>javassist</groupId><artifactId>javassist</artifactId><version>3.12.1.GA</version></dependency><dependency><groupId>org.ow2.asm</groupId><artifactId>asm-all</artifactId><version>5.1</version></dependency><dependency><groupId>net.bytebuddy</groupId><artifactId>byte-buddy</artifactId><version>1.5.7</version></dependency><dependency><groupId>net.bytebuddy</groupId><artifactId>byte-buddy-agent</artifactId><version>1.5.7</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><version>3.0.1</version><executions><execution><id>attach-sources</id><phase>verify</phase><goals><goal>jar-no-fork</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>2.6</version><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile></archive></configuration><executions><execution><id>assemble-all</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><executions><execution><phase>package</phase><goals><goal>shade</goal></goals></execution></executions><configuration><artifactSet><includes><include>javassist:javassist:jar:</include><include>net.bytebuddy:byte-buddy:jar:</include><include>net.bytebuddy:byte-buddy-agent:jar:</include></includes></artifactSet></configuration></plugin></plugins><resources><resource><directory>${basedir}/src/main/resources</directory></resource><resource><directory>${basedir}/src/main/java</directory></resource></resources></build>
</project>
?
AgentTime類
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;public class AgentTime {public static void premain(String agentArgs, Instrumentation inst) {System.out.println("監(jiān)控耗時(shí) >>>");// 添加 TransformerClassFileTransformer transformer = new PerformMonitorTransformer();inst.addTransformer(transformer);System.out.println("監(jiān)控耗時(shí) <<<");}
}
PerformMonitorTransformer類
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtBehavior;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;public class PerformMonitorTransformer implements ClassFileTransformer {private static final Set<String> classNameSet = new HashSet<>();static {classNameSet.add("com.book.test.TestTime");}@Overridepublic byte[] transform(ClassLoader loader,String className,Class<?> classBeingRedefined,ProtectionDomain protectionDomain,byte[] classfileBuffer) throws IllegalClassFormatException {//System.out.println("監(jiān)控耗時(shí) >>>1");try {String currentClassName = className.replaceAll("/", ".");if (!classNameSet.contains(currentClassName)) { // 僅僅提升Set中含有的類return null;}System.out.println("transform: [" + currentClassName + "]");CtClass ctClass = ClassPool.getDefault().get(currentClassName);CtBehavior[] methods = ctClass.getDeclaredBehaviors();for (CtBehavior method : methods) {System.out.println("method: [" + method + "]");enhanceMethod(method);}CtMethod m = ctClass.getDeclaredMethod("fun1");m.insertBefore("{ System.out.println($1); System.out.println($2); }"); return ctClass.toBytecode();} catch (Exception e) {e.printStackTrace();}return null;}private void enhanceMethod(CtBehavior method) throws Exception {if (method.isEmpty()) {return;}String methodName = method.getName();if (methodName.equalsIgnoreCase("main")) { // 不提升main方法return;}CtClass[] prams = method.getParameterTypes();if (prams.length > 0) {method.insertBefore("{ System.out.println($1);System.out.println($2); }");}final StringBuilder source = new StringBuilder();if (methodName.equalsIgnoreCase("fun3")) { // 修改fun3方法source.append("{").append("System.out.println(\"方法三真的被替換了\");").append("\n").append("}");} else {source.append("{").append("long start = System.nanoTime();\n") // 前置增強(qiáng): 打入時(shí)間戳.append("$_ = $proceed($$);\n") // 保留原有的代碼處理邏輯 .append("System.out.print(\"method:[" + methodName + ">>>]\");").append("\n").append("System.out.println(\" cost:[\" +(System.nanoTime() -start)+ \"ns]\");") // 后置增強(qiáng).append("}");}ExprEditor editor = new ExprEditor() {@Overridepublic void edit(MethodCall methodCall) throws CannotCompileException {methodCall.replace(source.toString());}};method.instrument(editor);}
}
被增強(qiáng)的項(xiàng)目:
TestAgent
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.book</groupId><artifactId>TestAgent</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><build><plugins><plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <appendAssemblyId>false</appendAssemblyId> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.book.test.TestTime</mainClass> </manifest> </archive></configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>assembly</goal> </goals> </execution> </executions> </plugin> </plugins></build>
</project>
?TestTime類
public class TestTime {private int fun1(int a,int b) {System.out.println("\n方法一開始>>>");return a+b;}private void fun2() {System.out.println("\n方法二開始>>>");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace(); }System.out.println("方法二結(jié)束<<<");}private void fun3() {System.out.println("方法三會(huì)被干掉么?"); }public static void main(String[] args) {TestTime test = new TestTime();test.fun1(2,3);test.fun2();test.fun3();}
}
運(yùn)行:
java ?-javaagent:E:\worktest\MyAgent\target\MyAgent-1.0-jar-with-dependencies.jar -jar E:\worktest\TestAgent\target\TestAgent-1.0-SNAPSHOT.jar com.book.test.TestTime
?
參考:https://blog.csdn.net/f59130/article/details/78481594
Javassist 使用指南(三)
總結(jié)
以上是生活随笔為你收集整理的Java字节码instrument研究的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM虚拟机参数配置官方文档
- 下一篇: GDB调试--以汇编语言为例