public class DetectDuplicatedCodeClassVisitor extends org.objectweb.asm.ClassVisitor
173: public void methodWithFinishBlock(FinishReturnTypeEnum f){
174: try {
175: switch (f) {
176: case BY_RETURN:
177: System.out.println("will return");
178: return;
179: case BY_THROW:
180: System.out.println("will throw");
181: throw new IllegalStateException("Expected exception");
182: default:
183: System.out.println("default");
184: }
185: } finally {
186: if (f != null) { //This piece of code is generated in ASM 3 times. We should merge it into one block
187: System.out.println("Finish with: f="+f);
188: }
189: }
190}
effects in generation such a JVM code:
// access flags 1
public methodWithFinishBlock(Ltest/performance/Test1$FinishReturnTypeEnum;)V
TRYCATCHBLOCK L0 L1 L2
TRYCATCHBLOCK L3 L2 L2
L0
LINENUMBER 175 L0
INVOKESTATIC test/performance/Test1.$SWITCH_TABLE$test$performance$Test1$FinishReturnTypeEnum()[I
ALOAD 1
INVOKEVIRTUAL test/performance/Test1$FinishReturnTypeEnum.ordinal()I
IALOAD
TABLESWITCH
1: L4
2: L3
default: L5
L4
LINENUMBER 177 L4
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "will return"
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L1
LINENUMBER 186 L1
ALOAD 1
IFNULL L6
L7
LINENUMBER 187 L7
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
NEW java/lang/StringBuilder
DUP
LDC "Finish with: f="
INVOKESPECIAL java/lang/StringBuilder.(Ljava/lang/String;)V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L6
LINENUMBER 178 L6
RETURN
L3
LINENUMBER 180 L3
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "will throw"
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L8
LINENUMBER 181 L8
NEW java/lang/IllegalStateException
DUP
LDC "Expected exception"
INVOKESPECIAL java/lang/IllegalStateException.(Ljava/lang/String;)V
ATHROW
L5
LINENUMBER 183 L5
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "default"
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
GOTO L9
L2
LINENUMBER 185 L2
ASTORE 2
L10
LINENUMBER 186 L10
ALOAD 1
IFNULL L11
L12
LINENUMBER 187 L12
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
NEW java/lang/StringBuilder
DUP
LDC "Finish with: f="
INVOKESPECIAL java/lang/StringBuilder.(Ljava/lang/String;)V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L11
LINENUMBER 189 L11
ALOAD 2
ATHROW
L9
LINENUMBER 186 L9
ALOAD 1
IFNULL L13
L14
LINENUMBER 187 L14
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
NEW java/lang/StringBuilder
DUP
LDC "Finish with: f="
INVOKESPECIAL java/lang/StringBuilder.(Ljava/lang/String;)V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L13
LINENUMBER 190 L13
RETURN
L15
LOCALVARIABLE this Ltest/performance/Test1; L0 L15 0
LOCALVARIABLE f Ltest/performance/Test1$FinishReturnTypeEnum; L0 L15 1
MAXSTACK = 4
MAXLOCALS = 3
Note that 'LINENUMBER 186' instruction occurs many times and code after that instruction is nearly identical
(see CodeFootstamp criteria of 'identity').
On the other hand duplicated 'LINENUMBER 186' instruction could happened for for example for 'for' loop. In this case the code after this instruction is different.
The goal of this class is to provide duplicatedLinesCollector that is map of:
(line number -> (duplicated lineId -> origin lineId)).
| Modifier and Type | Field and Description |
|---|---|
private java.lang.String |
className
Name (internal asm) of currently processed class
|
private java.util.Map<java.lang.Integer,java.util.Map<java.lang.Integer,java.lang.Integer>> |
duplicatedLinesCollector
map of (line number -> (duplicated lineId -> origin lineId))
|
private java.util.concurrent.atomic.AtomicInteger |
lineIdGenerator
Every LINENUMBER instruction will have generated it's lineId.
|
| Constructor and Description |
|---|
DetectDuplicatedCodeClassVisitor(org.objectweb.asm.ClassVisitor cv) |
| Modifier and Type | Method and Description |
|---|---|
java.util.Map<java.lang.Integer,java.util.Map<java.lang.Integer,java.lang.Integer>> |
getDuplicatesLinesCollector()
Returns map of (line number -> (duplicated lineId -> origin lineId))
|
void |
visit(int version,
int access,
java.lang.String name,
java.lang.String signature,
java.lang.String superName,
java.lang.String[] interfaces) |
org.objectweb.asm.MethodVisitor |
visitMethod(int access,
java.lang.String methodName,
java.lang.String description,
java.lang.String signature,
java.lang.String[] exceptions) |
private java.util.Map<java.lang.Integer,java.util.Map<java.lang.Integer,java.lang.Integer>> duplicatedLinesCollector
private java.lang.String className
private final java.util.concurrent.atomic.AtomicInteger lineIdGenerator
AbstractFindTouchPointsClassInstrumenter.lineIdGenerator )public DetectDuplicatedCodeClassVisitor(org.objectweb.asm.ClassVisitor cv)
public void visit(int version, int access, java.lang.String name, java.lang.String signature, java.lang.String superName, java.lang.String[] interfaces)
visit in class org.objectweb.asm.ClassVisitorpublic org.objectweb.asm.MethodVisitor visitMethod(int access, java.lang.String methodName, java.lang.String description, java.lang.String signature, java.lang.String[] exceptions)
visitMethod in class org.objectweb.asm.ClassVisitorpublic java.util.Map<java.lang.Integer,java.util.Map<java.lang.Integer,java.lang.Integer>> getDuplicatesLinesCollector()