169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage test.javassist.bytecode.analysis; 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException; 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException; 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool; 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass; 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtMethod; 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.NotFoundException; 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.AccessFlag; 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.Bytecode; 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.MethodInfo; 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.Opcode; 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.analysis.Subroutine; 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.analysis.SubroutineScanner; 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport junit.framework.TestCase; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Tests Subroutine Scanner 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @author Jason T. Greene 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class ScannerTest extends TestCase { 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void testNestedFinally() throws Exception { 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassPool pool = ClassPool.getDefault(); 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal generate(pool); 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass clazz = pool.get("test.ScannerTest$GeneratedTest"); 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod method = clazz.getDeclaredMethod("doit"); 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SubroutineScanner scanner = new SubroutineScanner(); 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Subroutine[] subs = scanner.scan(method.getMethodInfo2()); 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 31, 31, new int[]{125, 25}); 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 32, 31, new int[]{125, 25}); 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 33, 31, new int[]{125, 25}); 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 60, 31, new int[]{125, 25}); 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 61, 31, new int[]{125, 25}); 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 63, 31, new int[]{125, 25}); 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 66, 31, new int[]{125, 25}); 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 69, 31, new int[]{125, 25}); 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 71, 31, new int[]{125, 25}); 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 74, 31, new int[]{125, 25}); 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 76, 31, new int[]{125, 25}); 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 77, 77, new int[]{111, 71}); 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 79, 77, new int[]{111, 71}); 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 80, 77, new int[]{111, 71}); 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 82, 77, new int[]{111, 71}); 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 85, 77, new int[]{111, 71}); 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 88, 77, new int[]{111, 71}); 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 90, 77, new int[]{111, 71}); 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 93, 77, new int[]{111, 71}); 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 95, 77, new int[]{111, 71}); 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 96, 96, new int[]{106, 90}); 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 98, 96, new int[]{106, 90}); 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 99, 96, new int[]{106, 90}); 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 101, 96, new int[]{106, 90}); 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 104, 96, new int[]{106, 90}); 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 106, 77, new int[]{111, 71}); 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 109, 77, new int[]{111, 71}); 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 111, 31, new int[]{125, 25}); 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 114, 31, new int[]{125, 25}); 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 117, 31, new int[]{125, 25}); 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 118, 31, new int[]{125, 25}); 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 120, 31, new int[]{125, 25}); 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal verifySubroutine(subs, 123, 31, new int[]{125, 25}); 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static void verifySubroutine(Subroutine[] subs, int pos, int start, 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int[] callers) { 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Subroutine sub = subs[pos]; 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal assertNotNull(sub); 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal assertEquals(sub.start(), start); 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < callers.length; i++) 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal assertTrue(sub.callers().contains(new Integer(callers[i]))); 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static void generate(ClassPool pool) throws CannotCompileException, IOException, NotFoundException { 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Generated from eclipse JDK4 compiler: 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // public void doit(int x) { 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // println("null"); 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // try { 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // println("try"); 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // } catch (RuntimeException e) { 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // e.printStackTrace(); 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // } finally { 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // switch (x) { 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // default: 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // case 15: 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // try { 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // println("inner-try"); 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // } finally { 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // try { 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // println("inner-inner-try"); 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // } finally { 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // println("inner-finally"); 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // } 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // } 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // break; 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // case 1789: 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // println("switch -17"); 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // } 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // } 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal //} 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass clazz = pool.makeClass("test.ScannerTest$GeneratedTest"); 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtMethod method = new CtMethod(CtClass.voidType, "doit", new CtClass[] {CtClass.intType}, clazz); 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MethodInfo info = method.getMethodInfo2(); 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal info.setAccessFlags(AccessFlag.PUBLIC); 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass stringClass = pool.get("java.lang.String"); 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Bytecode code = new Bytecode(info.getConstPool(), 2, 9); 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 0 */ code.addAload(0); 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 1 */ code.addLdc("start"); 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 3 */ code.addInvokevirtual(clazz, "println", CtClass.voidType, new CtClass[] {stringClass}); 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 6 */ code.addAload(0); 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 7 */ code.addLdc("try"); 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 9 */ code.addInvokevirtual(clazz, "println", CtClass.voidType, new CtClass[] {stringClass}); 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 12 */ addJump(code, Opcode.GOTO, 125); 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 14 */ code.addAstore(2); 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 16 */ code.addAload(2); 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 17 */ code.addInvokevirtual("java.lang.Exception", "printStackTrace", "()V"); 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 20 */ addJump(code, Opcode.GOTO, 125); 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 23 */ code.addAstore(4); 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 25 */ addJump(code, Opcode.JSR, 31); 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 28 */ code.addAload(4); 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 30 */ code.addOpcode(Opcode.ATHROW); 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 31 */ code.addAstore(3); 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 32 */ code.addIload(1); 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int spos = code.currentPc(); 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 33 */ code.addOpcode(Opcode.LOOKUPSWITCH); 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addIndex(0); // 2 bytes pad - gets us to 36 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.add32bit(60 - spos); // default 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.add32bit(2); // 2 pairs 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.add32bit(15); code.add32bit(60 - spos); 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.add32bit(1789); code.add32bit(117 - spos); 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 60 */ code.addAload(0); 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 61 */ code.addLdc("inner-try"); 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 63 */ code.addInvokevirtual(clazz, "println", CtClass.voidType, new CtClass[] {stringClass}); 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 66 */ addJump(code, Opcode.GOTO, 111); 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 69 */ code.addAstore(6); 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 71 */ addJump(code, Opcode.JSR, 77); 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 74 */ code.addAload(6); 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 76 */ code.add(Opcode.ATHROW); 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 77 */ code.addAstore(5); 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 79 */ code.addAload(0); 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 80 */ code.addLdc("inner-inner-try"); 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 82 */ code.addInvokevirtual(clazz, "println", CtClass.voidType, new CtClass[] {stringClass}); 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 85 */ addJump(code, Opcode.GOTO, 106); 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 88 */ code.addAstore(8); 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 90 */ addJump(code, Opcode.JSR, 96); 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 93 */ code.addAload(8); 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 95 */ code.add(Opcode.ATHROW); 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 96 */ code.addAstore(7); 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 98 */ code.addAload(0); 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 99 */ code.addLdc("inner-finally"); 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 101 */ code.addInvokevirtual(clazz, "println", CtClass.voidType, new CtClass[] {stringClass}); 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 104 */ code.addRet(7); 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 106 */ addJump(code, Opcode.JSR, 96); 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 109 */ code.addRet(5); 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 111 */ addJump(code, Opcode.JSR, 77); 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 114 */ addJump(code, Opcode.GOTO, 123); 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 117 */ code.addAload(0); 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 118 */ code.addLdc("switch - 1789"); 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 120 */ code.addInvokevirtual(clazz, "println", CtClass.voidType, new CtClass[] {stringClass}); 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 123 */ code.addRet(3); 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 125 */ addJump(code, Opcode.JSR, 31); 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 128 */ code.addOpcode(Opcode.RETURN); 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addExceptionHandler(6, 12, 15, "java.lang.RuntimeException"); 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addExceptionHandler(6, 20, 23, 0); 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addExceptionHandler(125, 128, 23, 0); 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addExceptionHandler(60, 69, 69, 0); 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addExceptionHandler(111, 114, 69, 0); 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addExceptionHandler(79, 88, 88, 0); 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addExceptionHandler(106, 109, 88, 0); 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal info.setCodeAttribute(code.toCodeAttribute()); 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.addMethod(method); 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz.writeFile("/tmp"); 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static void addJump(Bytecode code, int opcode, int pos) { 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int current = code.currentPc(); 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addOpcode(opcode); 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addIndex(pos - current); 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 186