每个程序都是从main方法开始执行,指定javaagent后,则可以在main方法前执行agent的premain方法。
下面说下结合javassist修改指定类的字节码信息,实现方法延时的统计功能。
public class Test001 implements ClassFileTransformer { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (!"easylog/EasyLog".equals(className)) { return null; } try { ClassPool pool = ClassPool.getDefault(); CtClass clazz = pool.get("easylog.EasyLog"); for (CtConstructor constructor : clazz.getConstructors()) { constructor.addLocalVariable("c", CtClass.longType); constructor.insertBefore("System.out.println(\"====== before =====\");"); constructor.insertBefore("c = System.currentTimeMillis();"); constructor.insertAfter("System.out.println(\"time use: \" + (System.currentTimeMillis() - c));"); constructor.insertAfter("System.out.println(\"====== end =====\");"); } byte[] byteCode = clazz.toBytecode(); clazz.detach(); return byteCode; } catch (Exception e) { e.printStackTrace(); } return null; } }
public class PreMain { public static void premain(String agentArgs, Instrumentation inst) { System.out.println("params " + agentArgs); inst.addTransformer(new Test001()); } }
Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Build-Jdk: 1.8.0_161 Main-Class: main.AppMain Premain-Class: main.PreMain
java -javaagent:javaagent-1.0.jar=name,aa=name -jar …/main.jar
其中javaagent-1.0.jar是我们刚才打包好的程序
=name,aa=name是我们指定的参数
main.jar是其他业务程序
我们可以通过上述方式无侵入的方式统计其他业务程序指定方法的延时情况。