无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点这里以跳转到教程。
构建javaassist入门实例:
场景;
监控每个方法的执行时间
方式:
通过javaassist实现
代码:
package com.sirding;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
public class MyAgent {
private static Instrumentation inst = null;
public static void premain(String agentArgs, Instrumentation _inst){
System.out.println("PerfMonAgent.premian() was called.");
inst = _inst;
ClassFileTransformer trans = new MyTransform();
System.out.println("Adding a PerfMonXformer instance to the JVM.");
inst.addTransformer(trans);
}
}
package com.sirding;
import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtBehavior;
import javassist.CtClass;
import javassist.NotFoundException;
public class MyTransform implements ClassFileTransformer{
@Override
public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
byte[] transformed = null;
System.out.println("Transforming " + className);
ClassPool pool = ClassPool.getDefault();
CtClass cl = null;
try {
cl = pool.makeClass(new ByteArrayInputStream(classfileBuffer));
if(!cl.isInterface()) {
CtBehavior[] methods = cl.getDeclaredBehaviors();
for(CtBehavior method : methods){
doMethod(method);
}
transformed = cl.toBytecode();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(cl != null){
cl.detach();
}
}
return transformed;
}
private void doMethod(CtBehavior method) throws NotFoundException, CannotCompileException {
if("myTest".equalsIgnoreCase(method.getName())){
//添加局部变量,如果不同过addLocalVariable设置,在调用属性时将出现compile error: no such field: startTime
method.addLocalVariable("startTime", CtClass.longType);
method.insertBefore("System.out.println(startTime);");
method.insertBefore("startTime = System.currentTimeMillis();");
// method.insertBefore("long startTime = System.currentTimeMillis();System.out.println(startTime);");
method.insertBefore("System.out.println(\"insert before ......\");");
method.insertAfter("System.out.println(\"leave " + method.getName() + " and time is :\" + (System.currentTimeMillis() - startTime));");
}
}
}
pom.xml用于生成jar
4.0.0
com.sirding
java-inst
1
jar
java-inst
http://maven.apache.org
UTF-8
junit
junit
4.12
test
org.javassist
javassist
3.20.0-GA
org.apache.maven.plugins
maven-jar-plugin
2.4
com.sirding.MyAgent com.sirding.MyAgent
自己的系统路径/Maven/repo_3.3.3/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA.jar org.apache.maven.plugins maven-surefire-plugin true org.apache.maven.plugins maven-compiler-plugin 3.5.1 1.8 自己的系统路径/Maven/repo_3.3.3/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA.jar org.apache.maven.plugins maven-surefire-plugin true org.apache.maven.plugins maven-compiler-plugin 3.5.1 1.8
通过maven将上述的项目打java-inst.jar
编写测试类
public class Test{
public static void main(String[] args){
System.out.println("hello world");
new Test().myTest();
}
public void myTest(){
System.out.println("===============================================");
}
}
将Test.java java-inst.jar放在同一个文件中,执行如下命令
javac Test.java 生成Test.class
java -javaassist:java-inst.jar Test
C:\yrtz\test\aa>java -javaagent:java-inst-1.jar Test
PerfMonAgent.premian() was called.
Adding a PerfMonXformer instance to the JVM.
Transforming java/lang/invoke/MethodHandleImpl
Transforming java/lang/invoke/MethodHandleImpl$1
Transforming java/lang/invoke/MethodHandleImpl$2
Transforming java/util/function/Function
Transforming java/lang/invoke/MethodHandleImpl$3
Transforming java/lang/invoke/MethodHandleImpl$4
Transforming java/lang/ClassValue
Transforming java/lang/ClassValue$Entry
Transforming java/lang/ClassValue$Identity
Transforming java/lang/ClassValue$Version
Transforming java/lang/invoke/MemberName$Factory
Transforming java/lang/invoke/MethodHandleStatics
Transforming java/lang/invoke/MethodHandleStatics$1
Transforming sun/misc/PostVMInitHook
Transforming sun/usagetracker/UsageTrackerClient
Transforming java/util/concurrent/atomic/AtomicBoolean
Transforming sun/usagetracker/UsageTrackerClient$1
Transforming sun/usagetracker/UsageTrackerClient$4
Transforming sun/usagetracker/UsageTrackerClient$2
Transforming java/lang/ProcessEnvironment
Transforming java/lang/ProcessEnvironment$NameComparator
Transforming java/lang/ProcessEnvironment$EntryComparator
Transforming java/util/Collections$UnmodifiableMap
Transforming java/lang/ProcessEnvironment$CheckedEntrySet
Transforming java/util/HashMap$EntrySet
Transforming java/lang/ProcessEnvironment$CheckedEntrySet$1
Transforming java/util/HashMap$EntryIterator
Transforming java/util/HashMap$HashIterator
Transforming java/lang/ProcessEnvironment$CheckedEntry
Transforming sun/usagetracker/UsageTrackerClient$3
Transforming java/io/FileOutputStream$1
Transforming sun/launcher/LauncherHelper
Transforming sun/misc/URLClassPath$FileLoader$1
Transforming Test
Transforming sun/launcher/LauncherHelper$FXHelper
Transforming java/lang/Class$MethodArray
hello world
insert before ......
1492659861901
===============================================
leave myTest and time is :24
Transforming java/lang/Shutdown
Transforming java/lang/Shutdown$Lock
可以看到“leave myTest and time is :24”通过静态代理,动态的更新执行的method的二进制编码,有效的统计方法执行的时间
PS:
如果在动态添加局部变量时出现如下异常
javassist.CannotCompileException: [source error] no such field: startTime
at javassist.CtBehavior.insertAfter(CtBehavior.java:877)
at javassist.CtBehavior.insertAfter(CtBehavior.java:792)
at com.sirding.Perfmonxformer.doMethod(Perfmonxformer.java:49)
at com.sirding.Perfmonxformer.transform(Perfmonxformer.java:27)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
Caused by: compile error: no such field: startTime
at javassist.compiler.TypeChecker.fieldAccess(TypeChecker.java:845)
at javassist.compiler.TypeChecker.atFieldRead(TypeChecker.java:803)
at javassist.compiler.TypeChecker.atMember(TypeChecker.java:988)
at javassist.compiler.JvstTypeChecker.atMember(JvstTypeChecker.java:66)
at javassist.compiler.ast.Member.accept(Member.java:39)
at javassist.compiler.TypeChecker.atBinExpr(TypeChecker.java:329)
at javassist.compiler.ast.BinExpr.accept(BinExpr.java:41)
at javassist.compiler.TypeChecker.atPlusExpr(TypeChecker.java:371)
at javassist.compiler.TypeChecker.atBinExpr(TypeChecker.java:312)
at javassist.compiler.ast.BinExpr.accept(BinExpr.java:41)
at javassist.compiler.JvstTypeChecker.atMethodArgs(JvstTypeChecker.java:221)
at javassist.compiler.TypeChecker.atMethodCallCore(TypeChecker.java:735)
at javassist.compiler.TypeChecker.atCallExpr(TypeChecker.java:695)
at javassist.compiler.JvstTypeChecker.atCallExpr(JvstTypeChecker.java:157)
at javassist.compiler.ast.CallExpr.accept(CallExpr.java:46)
at javassist.compiler.CodeGen.doTypeCheck(CodeGen.java:242)
at javassist.compiler.CodeGen.atStmnt(CodeGen.java:330)
at javassist.compiler.ast.Stmnt.accept(Stmnt.java:50)
at javassist.compiler.Javac.compileStmnt(Javac.java:569)
at javassist.CtBehavior.insertAfterAdvice(CtBehavior.java:892)
at javassist.CtBehavior.insertAfter(CtBehavior.java:851)
... 18 more
确保 你在执行method.addLocalVariable("startTime", CtClass.longType);操作,对要使用的局部变量进行了定义。