package test.asm.aop; import static org.objectweb.asm.Opcodes.DUP; import static org.objectweb.asm.Opcodes.GETSTATIC; import static org.objectweb.asm.Opcodes.INVOKESPECIAL; import static org.objectweb.asm.Opcodes.INVOKESTATIC; import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL; import static org.objectweb.asm.Opcodes.NEW; import java.io.IOException; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; public class MethodTracClassLoader extends ClassLoader { @SuppressWarnings("unchecked") public <T> T load(Class<T> type, String name) { try { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassVisitor ana = new MethodAnalysis(cw); ClassReader classReader = new ClassReader(name); classReader.accept(ana, ClassReader.SKIP_FRAMES); byte[] code = cw.toByteArray(); Object o = this.defineClass(name, code, 0, code.length).newInstance(); return (T) o; } catch (ClassFormatError e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } public static void main(String[] args) { // try { // // Class<?> exampleClass = new // MethodTracClassLoader().load(Sample.class); // Method m = exampleClass.getMethod("main", String[].class); // m.invoke(null, new Object[] { null }); // // } catch (Exception e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } } class MethodAnalysis extends ClassVisitor { public MethodAnalysis(ClassVisitor cv) { super(Opcodes.ASM4, cv); } String className; @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { className = name; super.visit(version, access, name, signature, superName, interfaces); } public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { // final String methodName = name; // System.out.println(name); if ("<init>".equals(name) || (Opcodes.ACC_STATIC & access) > 0) { return cv.visitMethod(access, name, desc, signature, exceptions); } else { MethodVisitor mv; mv = cv.visitMethod(access, name, desc, signature, exceptions); mv = new AddSecurityCheckMethodAdapter(mv, name); return mv; } } class AddSecurityCheckMethodAdapter extends MethodVisitor { String name; public AddSecurityCheckMethodAdapter(MethodVisitor mv, String name) { super(Opcodes.ASM4, mv); this.name = name; } public void visitCode() { mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitLdcInsn("** - exec " + name + " at "); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V"); mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "nanoTime", "()J"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(J)Ljava/lang/StringBuilder;"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); } } // // // public MethodVisitor visitMethod(final int access, final String name, // final String desc, // final String signature, final String[] exceptions) { // // // final String methodName = name; // // System.out.println(name); // // if ("<init>".equals(name) || (Opcodes.ACC_STATIC & access) > 0) { // return cv.visitMethod(access, name, desc, signature, exceptions); // } else { // String newName = name + "_hide"; // MethodVisitor mv; // ClassVisitor cw = cv; // { // mv = cw.visitMethod(access, name, desc, signature, exceptions); // // if (desc.charAt(desc.length() - 1) != 'V') { // mv.visitCode(); // mv.visitInsn(RETURN); // mv.visitMaxs(0, 1); // mv.visitEnd(); // } else { // mv.visitCode(); // mv.visitInsn(ACONST_NULL); // mv.visitInsn(ARETURN); // mv.visitMaxs(1, 1); // mv.visitEnd(); // } // // // mv.visitCode(); // // mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", // // "Ljava/io/PrintStream;"); // // mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); // // mv.visitInsn(DUP); // // mv.visitLdcInsn("** - exec " + name + " at "); // // mv.visitMethodInsn(INVOKESPECIAL, // // "java/lang/StringBuilder", "<init>", // // "(Ljava/lang/String;)V"); // // mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", // // "currentTimeMillis", "()J"); // // mv.visitMethodInsn(INVOKEVIRTUAL, // // "java/lang/StringBuilder", "append", // // "(J)Ljava/lang/StringBuilder;"); // // mv.visitMethodInsn(INVOKEVIRTUAL, // // "java/lang/StringBuilder", "toString", // // "()Ljava/lang/String;"); // // mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", // // "println", "(Ljava/lang/String;)V"); // // // // // mv.visitVarInsn(ALOAD, 0); // // mv.visitVarInsn(ALOAD, 1); // // mv.visitMethodInsn(INVOKESPECIAL, className, newName, // // desc); // // if (desc.charAt(desc.length() - 1) != 'V') { // // mv.visitInsn(ARETURN); // // } else { // // mv.visitInsn(RETURN); // // } // // mv.visitMaxs(0, 0); // // mv.visitEnd(); // } // // MethodVisitor mvRaw = cv.visitMethod(Opcodes.ACC_PRIVATE, // // newName, desc, signature, exceptions); // MethodVisitor mvRaw = cv.visitMethod(access, newName, desc, // signature, exceptions); // return mvRaw; // } // } } }