Files
corejava/corejava第10版/v2ch08/bytecodeAnnotations/EntryLogger.java
T
2019-05-22 19:31:49 +08:00

87 lines
2.9 KiB
Java

package bytecodeAnnotations;
import java.io.*;
import java.nio.file.*;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.*;
/**
* Adds "entering" logs to all methods of a class that have the LogEntry annotation.
* @version 1.20 2016-05-10
* @author Cay Horstmann
*/
public class EntryLogger extends ClassVisitor
{
private String className;
/**
* Constructs an EntryLogger that inserts logging into annotated methods of a given class.
* @param cg the class
*/
public EntryLogger(ClassWriter writer, String className)
{
super(Opcodes.ASM5, writer);
this.className = className;
}
@Override
public MethodVisitor visitMethod(int access, String methodName, String desc,
String signature, String[] exceptions)
{
MethodVisitor mv = cv.visitMethod(access, methodName, desc, signature, exceptions);
return new AdviceAdapter(Opcodes.ASM5, mv, access, methodName, desc)
{
private String loggerName;
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
{
return new AnnotationVisitor(Opcodes.ASM5)
{
public void visit(String name, Object value)
{
if (desc.equals("LbytecodeAnnotations/LogEntry;") && name.equals("logger"))
loggerName = value.toString();
}
};
}
public void onMethodEnter()
{
if (loggerName != null)
{
visitLdcInsn(loggerName);
visitMethodInsn(INVOKESTATIC, "java/util/logging/Logger", "getLogger",
"(Ljava/lang/String;)Ljava/util/logging/Logger;", false);
visitLdcInsn(className);
visitLdcInsn(methodName);
visitMethodInsn(INVOKEVIRTUAL, "java/util/logging/Logger", "entering",
"(Ljava/lang/String;Ljava/lang/String;)V", false);
loggerName = null;
}
}
};
}
/**
* Adds entry logging code to the given class.
* @param args the name of the class file to patch
*/
public static void main(String[] args) throws IOException
{
if (args.length == 0)
{
System.out.println("USAGE: java bytecodeAnnotations.EntryLogger classfile");
System.exit(1);
}
Path path = Paths.get(args[0]);
ClassReader reader = new ClassReader(Files.newInputStream(path));
ClassWriter writer = new ClassWriter(
ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
EntryLogger entryLogger = new EntryLogger(writer,
path.toString().replace(".class", "").replaceAll("[/\\\\]", "."));
reader.accept(entryLogger, ClassReader.EXPAND_FRAMES);
Files.write(Paths.get(args[0]), writer.toByteArray());
}
}