经常看到OpenJPA、Jacoco、cobertura等工具对Java Class进行Instrument操作, Java 从1.5开始也提供了instrument包,那么到底什么是instrument,为什么instrument,怎么instrument呢?
什么是instrument
平时我们写Java程序,都是编写**.java 文件,通过Javac编译成Java Class文件,Java Class文件直接被JVM load到内存中运行。我们是不会去修改Class文件的内容。如果我们发现有要修改的内容,我们要修改java文件然后重新编译生成新的class文件,而Instrument就是对Java Class文件进行修改。
为什么instrument
这个就很简单了,比较常见的应用就是提取通用功能,可以说成是一种AOP,我一般通用功能分两种:1. 实现一些common的功能(性能监控,安全),要进产品的(比如OpenJPA的Class enhancement)
2. 某些特殊环境才需要的功能,不用进产品的(比如cobertura用来检测覆盖率加的统计测试代码)。
怎么instrument
1. 使用asm/BCEL/javassist在JVM load class之前修改class文件,具体每种的实现可以参考reference里面各个的user guide,在Java1.5之前,大部分对class文件的修改都是直接使用这些三方包,比如AspectJ,比如cobertura2. 使用Java 1.5引进的新package instrument,Java Instrument 包含2个子包,最主要的是Java Instrumetation,可以用来在class被load之间执行preMain或者AgentMain,如果简单Class功能添加,可以只用到Java Instrumentation,如果需要复杂功能,可能需要结合ClassFileTransformer包以及1里面提到的第三方包对Class文件做详细修改。
Reference:
1. asm: http://asm.ow2.org/ BCEL: http://commons.apache.org/proper/commons-bcel/index.html javasist: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
2. cobertura Instrument implementation:
https://github.com/cobertura/cobertura/blob/master/cobertura/src/main/java/net/sourceforge/cobertura/instrument/InstrumentMain.java
https://github.com/cobertura/cobertura/blob/master/cobertura/src/main/java/net/sourceforge/cobertura/dsl/Cobertura.java
https://github.com/cobertura/cobertura/blob/master/cobertura/src/main/java/net/sourceforge/cobertura/instrument/CodeInstrumentationTask.java
https://github.com/cobertura/cobertura/blob/master/cobertura/src/main/java/net/sourceforge/cobertura/instrument/CoberturaInstrumenter.java instrumentClass(InputStreaminputStream)