import static org.objectweb.asm.Opcodes.*;
import java.io.*;
import org.objectweb.asm.*;
public class ClassNameInliner {
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream(args[0]);
ClassReader cr = new ClassReader(is);
ClassWriter cw = new ClassWriter(0);
cr.accept(new ClassVisitor(ASM6, cw) {
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
return new MethodVisitor(ASM6, super.visitMethod(access, name, descriptor, signature, exceptions)) {
private Type ldcType;
/*
* Strategy: Detect the pattern:
* - LDC <class>
* - INVOKEVIRTUAL java/lang/Class.getName()
*/
public void visitLdcInsn(Object value) {
if (value instanceof Type) {
/* Loading a Class type */
ldcType = (Type) value;
} else {
super.visitLdcInsn(value);
ldcType = null;
}
}
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
if (opcode == INVOKEVIRTUAL && "java/lang/Class".equals(owner) && "getName".equals(name)
&& "()Ljava/lang/String;".equals(descriptor) && !isInterface && ldcType != null) {
/* Having previously loaded a Class type and now calling getName() on it! */
super.visitLdcInsn(ldcType.getClassName());
} else {
if (ldcType != null)
super.visitLdcInsn(ldcType);
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
ldcType = null;
}
/* Make sure that all other instructions break the match pattern */
public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
super.visitFieldInsn(opcode, owner, name, descriptor);
ldcType = null;
}
public void visitMultiANewArrayInsn(String descriptor, int numDimensions) {
super.visitMultiANewArrayInsn(descriptor, numDimensions);
ldcType = null;
}
public void visitTypeInsn(int opcode, String type) {
super.visitTypeInsn(opcode, type);
ldcType = null;
}
public void visitIincInsn(int var, int increment) {
super.visitIincInsn(var, increment);
ldcType = null;
}
public void visitInsn(int opcode) {
super.visitInsn(opcode);
ldcType = null;
}
public void visitIntInsn(int opcode, int operand) {
super.visitIntInsn(opcode, operand);
ldcType = null;
}
public void visitJumpInsn(int opcode, Label label) {
super.visitJumpInsn(opcode, label);
ldcType = null;
}
public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
super.visitLookupSwitchInsn(dflt, keys, labels);
ldcType = null;
}
public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
super.visitTableSwitchInsn(min, max, dflt, labels);
ldcType = null;
}
public void visitVarInsn(int opcode, int var) {
super.visitVarInsn(opcode, var);
ldcType = null;
}
public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle,
Object... bootstrapMethodArguments) {
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
ldcType = null;
}
};
}
}, 0);
is.close();
/* Rewrite file */
byte[] arr = cw.toByteArray();
OutputStream fos = new FileOutputStream(args[0]);
fos.write(arr);
fos.flush();
fos.close();
}
}