一、技术点
1.1 技术点
在之前的方法中有一个参数:
-
public static void premain(String agentArgs, Instrumentation inst) {
-
System.out.println("Hello javaagent permain:"+agentArgs);
-
}
参数Instrumentation是一个接口,我们可以看下:
-
public interface Instrumentation {
-
/**
-
注册一个Transformer,从此之后的类加载都会被Transformer拦截。
-
* Transformer可以直接对类的字节码byte[]进行修改
-
* @since 1.6
-
*/
-
void
-
addTransformer(ClassFileTransformer transformer);
-
/**
-
* 对JVM已经加载的类重新触发类加载。使用的就是上面注册的Transformer。
-
* retransformation可以修改方法体,但是不能变更方法签名、增加和删除方法/类的成员属性
-
*
-
* @see #isRetransformClassesSupported
-
* @see #addTransformer
-
* @see java.lang.instrument.ClassFileTransformer
-
* @since 1.6
-
*/
-
void
-
retransformClasses(Class<?>... classes) throws UnmodifiableClassException;
-
/**
-
获取当前被JVM加载的所有类对象
-
*/
-
@SuppressWarnings("rawtypes")
-
Class[]
-
getAllLoadedClasses();
-
}
前面两个方法比较重要,addTransformer 方法配置之后,后续的类加载都会被 Transformer 拦截。对于已经加载过的类,可以执行 retransformClasses 来重新触发这个 Transformer 的拦截。类加载的字节码被修改后,除非再次被 retransform,否则不会恢复。
1.2 javaassist
直接修改字节码有点麻烦,因此我们借助神器javaassist来修改字节码。
Javassist (JAVA programming ASSISTant) 是在 Java 中编辑字节码的类库;它使 Java 程序能够在运行时定义一个新类, 并在 JVM 加载时修改类文件。
我们常用到的动态特性主要是反射,在运行时查找对象属性、方法,修改作用域,通过方法名称调用方法等。在线的应用不会频繁使用反射,因为反射的性能开销较大。其实还有一种和反射一样强大的特性,但是开销却很低,它就是Javassit。
二、实现
在接下来我看下如何统计方法的耗时。
。。。。。。。。。。。。。。。。。
版权原因,完整文章,请参考如下:「字节码插桩」统计方法耗时(第三篇:叱咤风云)- 第313篇