美文网首页
java-动态追踪技术

java-动态追踪技术

作者: jiangmo | 来源:发表于2019-02-27 09:55 被阅读0次

    JSP动态解析过程

    请求访问一个JSP文件的时候,整个过程是这样的:
    JSP文件修改过后,之所以能及时生效,是因为Web容器(Tomcat)会检查请求的JSP文件是否被更改过,如果发生过更改,那么就将JSP文件重新解析翻译成一个新的Sevlet类,并加载到JVM中,之后的请求,都会由这个新的Servet来处理。这里有个问题,根据Java的类加载机制,在同一个ClassLoader中,类是不允许重复的,为了绕开这个限制,Web容器每次都会创建一个新的ClassLoader实例,来加载新编译的Servlet类,之后的请求都会由这个新的Servlet来处理,这样就实现了新旧JSP的切换。

    HTTP服务是无状态的,所以JSP的场景基本上都是一次性消费,这种通过创建新的ClassLoader来“替换”class的做法行得通,但是对于其他应用,比如Spring框架,即便这样做了,对象多数是单例,对于内存中已经创建好的对象,我们无法通过这种创建新的ClassLoader实例的方法来修改对象行为。

    java.lang.instrument.Instrumentation

    看完文档之后,我们发现这么两个接口:reDefineClasses和reTransformClasses。一个是重新定义class,一个是修改class。

    直接操作字节码 ASM、CGLib

    BTrace

    https://github.com/btraceio/btrace
    BTrace是基于Java语言的一个安全的、可提供动态追踪服务的工具。BTrace基于ASM、Java Attach Api、Instruments开发,为用户提供了很多注解。依靠这些注解,我们可以编写BTrace脚本(简单的Java代码)达到我们想要的效果,而不必深陷于ASM对字节码的操作中不可自拔。

    
    package com.sun.btrace.samples;
    
    import com.sun.btrace.annotations.*;
    import com.sun.btrace.AnyType;
    import static com.sun.btrace.BTraceUtils.*;
    
    /**
     * This sample demonstrates regular expression
     * probe matching and getting input arguments
     * as an array - so that any overload variant
     * can be traced in "one place". This example
     * traces any "readXX" method on any class in
     * java.io package. Probed class, method and arg
     * array is printed in the action.
     */
    @BTrace public class ArgArray {
        @OnMethod(
            clazz="/java\\.io\\..*/",
            method="/read.*/"
        )
        public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
            println(pcn);
            println(pmn);
            printArray(args);
        }
    }
    
    package com.sun.btrace.samples;
    
    import com.sun.btrace.annotations.*;
    import static com.sun.btrace.BTraceUtils.*;
    import com.sun.btrace.annotations.Export;
    
    /**
     * This sample creates a jvmstat counter and
     * increments it everytime Thread.start() is
     * called. This thread count may be accessed
     * from outside the process. The @Export annotated
     * fields are mapped to jvmstat counters. The counter
     * name is "btrace." +  + "." + 
     */ 
    @BTrace public class ThreadCounter {
    
        // create a jvmstat counter using @Export
        @Export private static long count;
    
        @OnMethod(
            clazz="java.lang.Thread",
            method="start"
        ) 
        public static void onnewThread(@Self Thread t) {
            // updating counter is easy. Just assign to
            // the static field!
            count++;
        }
    
        @OnTimer(2000) 
        public static void ontimer() {
            // we can access counter as "count" as well
            // as from jvmstat counter directly.
            println(count);
            // or equivalently ...
            println(Counters.perfLong("btrace.com.sun.btrace.samples.ThreadCounter.count"));
        }
    }
    

    BTrace的架构是怎样的呢?

    BTrace主要有下面几个模块:

    • BTrace脚本:利用BTrace定义的注解,我们可以很方便地根据需要进行脚本的开发。

    • Compiler:将BTrace脚本编译成BTrace class文件。

    • Client:将class文件发送到Agent。

    • Agent:基于Java的Attach Api,Agent可以动态附着到一个运行的JVM上,然后开启一个BTrace Server,接收client发过来的BTrace脚本;解析脚本,然后根据脚本中的规则找到要修改的类;修改字节码后,调用Java Instrument的reTransform接口,完成对对象行为的修改并使之生效。

    Ref:

    相关文章

      网友评论

          本文标题:java-动态追踪技术

          本文链接:https://www.haomeiwen.com/subject/afkxuqtx.html