• java instrument跟踪java freemarker调用过程


    freemarker是一个java的模板引擎,我通常用来做代码生成工具。
    里面的源码有很多,所以我想有没有办法能把代码生成过程中的类名打印出来,这样我就能知道那些java文件是必须的。
    找了找动态代理的AOP,还看了看CGlib,感觉都不太方便。
    这时想起了以前看SwingSpy中用到的jdk1.5之后的一个东西,Instrument。很强大,也很好用。


    GenCode.java
    //FreeMarker 代码生成
    package cn.z;


    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    import java.util.HashMap;
    import java.util.Map;


    import freemarker.core.Environment;
    import freemarker.template.Configuration;
    import freemarker.template.DefaultObjectWrapper;
    import freemarker.template.Template;
    import freemarker.template.TemplateException;
    import freemarker.template.TemplateExceptionHandler;


    public class GenCode {


    /**
    * @param args
    * @throws IOException 
    * @throws TemplateException 
    */
    public static void main(String[] args) throws IOException, TemplateException {
    // 模板路径
    String dir = "template";
    Configuration cfg = new Configuration();
    // 加载freemarker模板文件
    cfg.setDirectoryForTemplateLoading(new File(dir));
    // 设置对象包装器
    cfg.setObjectWrapper(new DefaultObjectWrapper());
    // 设计异常处理器
    cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
    // 定义并设置数据
    Map<String, String> data = new HashMap<String, String>();
    data.put("persion", "小吴");
    // 获取指定模板文件
    Template template = cfg.getTemplate("ex.ftl");
    // 定义输入文件,默认生成在工程根目录
    Writer out = new OutputStreamWriter(new FileOutputStream("test.html"),
    "GBK");
    Environment env = template.createProcessingEnvironment(data, out);
    env.setOutputEncoding("GBK");
    env.process();
    System.out.println("successful");
    }
    }


    PerfMonAgent.java
    //Instrument中的代理类
    package cn.z;


    import java.lang.instrument.ClassFileTransformer;
    import java.lang.instrument.Instrumentation;


    public class PerfMonAgent {
        static private Instrumentation inst = null;
        /**
         * This method is called before the application’s main-method is called,
         * when this agent is specified to the Java VM.
         **/
        public static void premain(String agentArgs, Instrumentation _inst) {
            System.out.println("PerfMonAgent.premain() was called.");
            // Initialize the static variables we use to track information.
            inst = _inst;
            // Set up the class-file transformer.
            ClassFileTransformer trans = new PerfMonXformer();
            System.out.println("Adding a PerfMonXformer instance to the JVM.");
            inst.addTransformer(trans);
        }
    }


    PerfMonXformer.java
    //对类进行拦截,其中还可以对类方法之类的进行修改,跟Hook差不多。
    package cn.z;


    import java.lang.instrument.ClassFileTransformer;
    import java.lang.instrument.IllegalClassFormatException;
    import java.security.ProtectionDomain;


    public class PerfMonXformer implements ClassFileTransformer {


    @Override
    public byte[] transform(ClassLoader loader, String className,
                Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
                byte[] classfileBuffer)
    throws IllegalClassFormatException {
    byte[] transformed = null;
    if (className.startsWith("freemarker"))
    System.out.println(className);

       return transformed; //return null.不修改类
    }
    }


    MANIFEST.MF
    //必须正确配置,否则不会执行PerfMonAgent的premain
    Manifest-Version: 1.0
    Premain-Class: cn.z.PerfMonAgent



    执行过程,打包上面的代码为PerfMonAgent.jar,记得MANIFEST.MF要包含进去。


    命令行java -javaagent:PerfMonAgent.jar cn.z.GenCode


    然后执行过程中我们就能看到
    freemarker/template/ObjectWrapper
    freemarker/template/TemplateException
    freemarker/template/Configuration
    freemarker/core/Configurable
    freemarker/core/ArithmeticEngine
    freemarker/core/ArithmeticEngine
    freemarker/core/Configurable
    freemarker/core/ArithmeticEngine
    freemarker/core/ParseException
    freemarker/core/FMParserConstants
    freemarker/core/TemplateClassResolver
    freemarker/cache/CacheStorage
    freemarker/cache/TemplateLoader
    freemarker/template/TemplateExceptionHandler
    freemarker/template/TemplateExceptionHandler
    freemarker/template/TemplateExceptionHandler
    freemarker/template/TemplateExceptionHandler
    freemarker/template/TemplateExceptionHandler
    freemarker/ext/beans/BeansWrapper
    freemarker/template/TemplateModelException
    freemarker/ext/beans/SimpleMemberModel
    freemarker/ext/beans/MethodMap
    freemarker/ext/util/ModelFactory
    freemarker/ext/util/ModelCache
    freemarker/ext/beans/BeansModelCache
    freemarker/template/utility/UndeclaredThrowableException
    freemarker/template/TemplateHashModel
    freemarker/template/TemplateModel
    。。。。。。
    那些文件被调用了显而易见了。
    如果监视到方法一级的调用,我们就可以做一个代码覆盖率的统计了。

  • 相关阅读:
    你都这么拼了,面试官TM怎么还是无动于衷
    js中string转map的方法
    如何使用jmeter做一个功能的性能测试
    如何看待远程办公?
    vue.js指令v-for使用以及下标索引的获取
    v-charts x轴字体斜显示
    Linux-(inotify-tools&rsync)
    Linux-(type,vim)
    zab协议
    数据库的规范一览
  • 原文地址:https://www.cnblogs.com/marryZhan/p/2213899.html
Copyright © 2020-2023  润新知