1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| public class ProfilingAgent { public static void premain(String args, Instrumentation inst) { inst.addTransformer(new ProfilingTransformer()); } static class ProfilingTransformer implements ClassFileTransformer { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { if (className.startsWith("com/example/service/")) { ClassReader cr = new ClassReader(classfileBuffer); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) { @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); return new ProfilingMethodVisitor(mv, className, name); } }; cr.accept(cv, ClassReader.EXPAND_FRAMES); return cw.toByteArray(); } return null; } } static class ProfilingMethodVisitor extends AdviceAdapter { private final String className; private final String methodName; private Label startLabel = new Label(); protected ProfilingMethodVisitor(MethodVisitor mv, String className, String methodName) { super(Opcodes.ASM9, mv, null, null); this.className = className; this.methodName = methodName; } @Override protected void onMethodEnter() { mv.visitLabel(startLabel); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "nanoTime", "()J", false); mv.visitVarInsn(Opcodes.LSTORE, 1); } @Override protected void onMethodExit(int opcode) { if (opcode != ATHROW) { mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "nanoTime", "()J", false); mv.visitVarInsn(Opcodes.LLOAD, 1); mv.visitInsn(Opcodes.LSUB); mv.visitVarInsn(Opcodes.LSTORE, 3); mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder"); mv.visitInsn(Opcodes.DUP); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false); mv.visitLdcInsn("Method profiling: "); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitLdcInsn(className + "." + methodName); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitLdcInsn(" took "); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitVarInsn(Opcodes.LLOAD, 3); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(J)Ljava/lang/StringBuilder;", false); mv.visitLdcInsn(" ns"); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); } } } }
|