|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
Java编译的是字节码,跟C++相反,启动不够快,效率不够高,难以精确控制内存,但是优点是编程比C++容易,代码比较安全但是容易留下性能隐患,跨平台靠字节码在各个平台复制(一处编译到处调试)之前有写基于AOP的日记调试会商一种跟踪Java程序的办法,但不是很完善.厥后发明了Btrace,因为它借助静态字节码注进手艺,完成文雅且功效壮大.
只不外,用起来老是磕磕绊绊的,经常为了跟踪某个成绩,却花了年夜把的工夫调试Btrace的剧本.为此,我实验将几种跟踪形式固化成剧本模板,待用的时分往调剂一下正则表达式之类的.
跟踪历程常常是假定与考证的螺旋迭代历程,重复的用BTrace跟踪方针历程,总有那末几回稀里糊涂的不成用,最初不能不重启方针历程.若真是线上不克不及停的服务,我想这类体例仍是不靠谱啊.
为此,据决意本人的弄个用起来复杂,又能优秀撑持重复跟踪而不必重启方针历程的工具.
AOP
AOP是Btrace,jip1等浩瀚监测工具的中心头脑,用一段代码最简单申明:- publicvoidsay(Stringwords){Trace.enter();System.out.println(words);Trace.exit();}
复制代码 如上,Trace.enter()和Trace.exit()将say(words)内的代码围绕起来,对办法收支的举行切面的处置,即可猎取运转时的高低文,如:
- 挪用栈
- 以后线程
- 工夫损耗
- 参数与前往值
- 以后实例形态
完成的选择
完成切面的体例,我晓得的有以下几种:
代办署理(粉饰器)形式
计划形式中粉饰器形式和代办署理形式,只管办理的成绩域分歧,代码完成长短常类似,都可以完成切面处置,这里视为等价.仍旧用代码申明:- interfacePerson{voidsay(Stringwords);}classOfficerimplementsPerson{publicvoidsay(Stringwords){lie(words);}privatevoidlie(Stringwords){...}}classProxyimplementsPerson{privatefinalOfficerofficer;publicProxy(Officerofficer){this.officer=officer;}publicvoidsay(Stringwords){enter();officer.say(words);exit();}privatevoidenter(){...}privatevoidexit(){...}}Personp=newProxy(newOfficer());
复制代码 很分明,上述enter()和exit()是完成切面的中央,经由过程猎取Officer的Proxy实例,即可对Officer实例的举动举行跟踪.这类体例完成起来最复杂,也最间接.
JavaProxy
JavaProxy是JDK内置的代办署理API,借助反射机制完成.用它来是完成切面则会是:- classProxyInvocationHandlerimplementsInvocationHandler{privatefinalObjecttarget;publicProxyInvocationHandler(Objecttarget){this.target=target;}publicObjecthandle(Objectproxy,Methodmethod,Object[]args){enter();method.invoke(target,args);exit();}privatevoidenter(){...}privatevoidexit(){...}}ClassLoaderloader=...Class<?>[]interfaces={Person.class};Personp=(Person)Proxy.newInstance(loader,interfaces,newProxyInvocationHandler(newOfficer()));
复制代码 比拟较上一中办法,这类不太易读,但更加通用,对详细完成依附很少.
AspectJ
AspectJ3是基于字节码操纵的AOP完成,比拟较Javaproxy,它会显得对换用更”通明”,编写更简明(相似DSL),功能更好.以下代码:- pointcutsay():execute(*say(..))before():say(){...}after():say(){...}
复制代码 Aspectj完成切面的机会有两种:静态编译和类加载期编织(load-timeweaving).而且它对IDE的撑持很丰厚.
CGlib
与AspectJ一样CGlib4也是操纵字节码来完成AOP的,利用上与JavaProxy十分类似,只是不像JavaProxy对接口有依附,我们熟知的Spring,Guice之类的IoC容器完成AOP都是利用它来完成的.- classCallbackimplementsMethodInterceptor{publicObjectintercept(Objectobj,java.lang.reflect.Methodmethod,Object[]args,MethodProxyproxy)throwsThrowable{enter();proxy.invokeSuper(obj,args);exit();}privatevoidenter(){...}privatevoidexit(){...}}Enhancere=newEnhancer();e.setSuperclass(Officer.class);e.setCallback(newCallback());Personp=e.create();
复制代码 字节码利用
下面四种办法各有合用的场景,但惟独对运转着的Java历程举行静态的跟踪撑持不了,固然大概是我懂得的不敷深切,如有基于上述计划的举措还请不惜见教.
仍是回到Btrace5的思绪下去,在了解了它借助java.lang.Instrumentation举行字节码注进的完成道理6后,完成静态变更跟踪体例或方针应当没有成绩.
借上去的成绩,怎样操纵(注进)字节码完成切面的处置.可喜的是,“构建本人的监测工具”7一文给我供应了一个很好的切进点.在此基本上,经由一些对ASM8的深切研讨,能够完成:
- 办法挪用进进时,猎取以后实例(this)和参数值列表;
- 办法挪用进来时,猎取前往值;
- 办法非常抛出时,触发还调并猎取非常实例.
其切面完成的中心代码以下:- privatestaticclassProbeMethodAdapterextendsAdviceAdapter{protectedProbeMethodAdapter(MethodVisitormv,intaccess,Stringname,Stringdesc,StringclassName){super(mv,access,name,desc);start=newLabel();end=newLabel();methodName=name;this.className=className;}@OverridepublicvoidvisitMaxs(intmaxStack,intmaxLocals){mark(end);catchException(start,end,Type.getType(Throwable.class));dup();push(className);push(methodName);push(methodDesc);loadThis();invokeStatic(Probe.TYPE,Probe.EXIT);visitInsn(ATHROW);super.visitMaxs(maxStack,maxLocals);}@OverrideprotectedvoidonMethodEnter(){push(className);push(methodName);push(methodDesc);loadThis();loadArgArray();invokeStatic(Probe.TYPE,Probe.ENTRY);mark(start);}@OverrideprotectedvoidonMethodExit(intopcode){if(opcode==ATHROW)return;//donothing,@seevisitMaxprepareResultBy(opcode);push(className);push(methodName);push(methodDesc);loadThis();invokeStatic(Probe.TYPE,Probe.EXIT);}privatevoidprepareResultBy(intopcode){if(opcode==RETURN){//voidpush((Type)null);}elseif(opcode==ARETURN){//objectdup();}else{if(opcode==LRETURN||opcode==DRETURN){//longordoubledup2();}else{dup();}box(Type.getReturnType(methodDesc));}}privatefinalStringclassName;privatefinalStringmethodName;privatefinalLabelstart;privatefinalLabelend;}
复制代码 更多参考请见这里的Demo,它是javaagent,在陪伴宿主历程启动后,供应MBean可用jconsole举行静态跟踪的办理.
后续的偏向
- 供应基于Web的远程交互界面;
- 供应基于Shell的当地命令行接口;
- 供应Profile统计和趋向输入;
- 供应跟踪日记定位与剖析.
参考
- TheJavaInteractiveProfiler
- ProxyJavadoc
- Aspectj
- CGlib
- BTraceUser’sGuide
- java静态跟踪剖析工具BTrace完成道理
- 构建本人的监测工具
- ASMGuide
- 经常使用JavaProfiling工具的剖析与对照
- AOP@Work:PerformancemonitoringwithAspectJ
- TheJavaTMVirtualMachineSpecification
- 来自rednaxelafx的JVM分享,他的Blog
- BCEL
没有那个大公司会傻了吧唧用.net网页编程开发大型项目,开发了,那等于自己一半的生命线被微软握着呢。而.net网页编程不行,限制在window系统,又是捆绑,鄙视微软之! |
|