javaassist入门(一)-no such field:
来源:互联网 发布:2017双十一大数据分析 编辑:程序博客网 时间:2024/06/03 18:10
构建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{@Overridepublic 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: startTimemethod.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
<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.sirding</groupId><artifactId>java-inst</artifactId><version>1</version><packaging>jar</packaging><name>java-inst</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.20.0-GA</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.4</version><configuration><archive><manifestEntries>
<!-- 重点配置 --><Premain-Class>com.sirding.MyAgent</Premain-Class>
<!-- 依赖javaassit包路径 --><Boot-Class-Path>自己的系统路径/Maven/repo_3.3.3/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA.jar</Boot-Class-Path></manifestEntries></archive></configuration></plugin> <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><skip>true</skip></configuration></plugin><plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin></plugins></build></project>
通过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 TestPerfMonAgent.premian() was called.Adding a PerfMonXformer instance to the JVM.Transforming java/lang/invoke/MethodHandleImplTransforming java/lang/invoke/MethodHandleImpl$1Transforming java/lang/invoke/MethodHandleImpl$2Transforming java/util/function/FunctionTransforming java/lang/invoke/MethodHandleImpl$3Transforming java/lang/invoke/MethodHandleImpl$4Transforming java/lang/ClassValueTransforming java/lang/ClassValue$EntryTransforming java/lang/ClassValue$IdentityTransforming java/lang/ClassValue$VersionTransforming java/lang/invoke/MemberName$FactoryTransforming java/lang/invoke/MethodHandleStaticsTransforming java/lang/invoke/MethodHandleStatics$1Transforming sun/misc/PostVMInitHookTransforming sun/usagetracker/UsageTrackerClientTransforming java/util/concurrent/atomic/AtomicBooleanTransforming sun/usagetracker/UsageTrackerClient$1Transforming sun/usagetracker/UsageTrackerClient$4Transforming sun/usagetracker/UsageTrackerClient$2Transforming java/lang/ProcessEnvironmentTransforming java/lang/ProcessEnvironment$NameComparatorTransforming java/lang/ProcessEnvironment$EntryComparatorTransforming java/util/Collections$UnmodifiableMapTransforming java/lang/ProcessEnvironment$CheckedEntrySetTransforming java/util/HashMap$EntrySetTransforming java/lang/ProcessEnvironment$CheckedEntrySet$1Transforming java/util/HashMap$EntryIteratorTransforming java/util/HashMap$HashIteratorTransforming java/lang/ProcessEnvironment$CheckedEntryTransforming sun/usagetracker/UsageTrackerClient$3Transforming java/io/FileOutputStream$1Transforming sun/launcher/LauncherHelperTransforming sun/misc/URLClassPath$FileLoader$1Transforming TestTransforming sun/launcher/LauncherHelper$FXHelperTransforming java/lang/Class$MethodArrayhello worldinsert before ......1492659861901===============================================leave myTest and time is :24Transforming java/lang/ShutdownTransforming 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);操作,对要使用的局部变量进行了定义。
0 0
- javaassist入门(一)-no such field:
- android studio debug no such instance field
- javaassist
- 自定义view中 case MotionEvent.ACTION_DOWN:No such instance field:
- no such还是no such a
- SIOCADDRT: no such process
- SIOCADDRT: no such process
- SIOCADDRT: No such process
- SIOCADDRT: No such process
- SIOCADDRT:no such process
- setsockopt:no such device
- (1) no such column
- No such filter: 'drawtext'
- sqlite no such table
- No such module alamofire
- no such process
- GitLab: No such project
- No such filter: 'drawtext'
- 安卓多点触摸的问题
- SVN 操作出现 locked 错误解决办法
- 基于Spring可扩展Schema提供自定义配置支持(转载)
- MySQL索引背后的数据结构及算法原理
- 第三届全国网络空间安全技术大赛 Web补题 By Assassin(持续更新)
- javaassist入门(一)-no such field:
- Android实战-怎样获取到Android控件的高度
- iOS黑魔法--Method Swizzling
- windows下MyEclipse初次配置hadoop问题
- 登陆界面验证程序,缺少 'End' ?高分相送。谢谢
- ubuntu 桌面找回
- asp+access 时间问题
- 文章标题
- 二叉树面试题(二)---求一颗二叉树的镜像