/** * Override this method to create you own classes on the fly. The name contains the special token * $$BCEL$$. Everything before that token is consddered to be a package name. You can encode you * own arguments into the subsequent string. You must regard however not to use any "illegal" * characters, i.e., characters that may not appear in a Java class name too<br> * The default implementation interprets the string as a encoded compressed Java class, unpacks * and decodes it with the Utility.decode() method, and parses the resulting byte array and * returns the resulting JavaClass object. * * @param class_name compressed byte code with "$$BCEL$$" in it */ protected JavaClass createClass(String class_name) { int index = class_name.indexOf("$$BCEL$$"); String real_name = class_name.substring(index + 8); JavaClass clazz = null; try { byte[] bytes = Utility.decode(real_name, true); ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo"); clazz = parser.parse(); } catch (Throwable e) { e.printStackTrace(); return null; } // Adapt the class name to the passed value ConstantPool cp = clazz.getConstantPool(); ConstantClass cl = (ConstantClass) cp.getConstant(clazz.getClassNameIndex(), Constants.CONSTANT_Class); ConstantUtf8 name = (ConstantUtf8) cp.getConstant(cl.getNameIndex(), Constants.CONSTANT_Utf8); name.setBytes(class_name.replace('.', '/')); return clazz; }
@Test public void shouldReturnUnparsableClassIfErrorOccursWhileParsing() { ClassParser parser = mock(ClassParser.class); when(parser.getClass("MyClassName")).thenThrow(new RuntimeException(new NotFoundException(""))); builder = new JavaClassBuilder(parser); Assert.assertThat(builder.createClass("MyClassName"), instanceOf(UnparsableClass.class)); }
private DbJVPackage importJarFile( File jarFile, DbJVPackage topMostPackage, Controller controller, int startJobDone, int endJobDone) throws DbException { DbJVClass dbClass; String filename = jarFile.getName(); try { ZipFile zip = new ZipFile(jarFile); int i = 0, nb = zip.size(); int span = endJobDone - startJobDone; for (Enumeration<?> e = zip.entries(); e.hasMoreElements(); ) { int jobDone = startJobDone + (i * span) / nb; ZipEntry entry = (ZipEntry) e.nextElement(); String entryName = entry.getName(); int idx = entryName.lastIndexOf('.'); String ext = (idx == -1) ? null : entryName.substring(idx + 1); if ("class".equals(ext)) { InputStream is = zip.getInputStream(entry); ClassParser parser = new ClassParser(is, filename); JavaClass claz = parser.parse(); dbClass = importClass(claz, controller); if (dbClass != null) { DbJVPackage pack = (DbJVPackage) dbClass.getCompositeOfType(DbJVPackage.metaClass); topMostPackage = findTopMostPackage(topMostPackage, pack); addToImportedPackage(pack); } // end if } // end if // check job done controller.checkPoint(jobDone); i++; // stop to reverse engineer if user has cancelled boolean finished = controller.isFinalState(); if (finished) { break; } } // end for zip.close(); } catch (IOException ex) { controller.println(ex.toString()); dbClass = null; } return topMostPackage; } // end importClassFile()
private DbJVClass importClassFile(String filename, Controller controller) throws DbException { DbJVClass dbClass; try { ClassParser parser = new ClassParser(filename); JavaClass claz = parser.parse(); dbClass = importClass(claz, controller); } catch (IOException ex) { controller.println(ex.toString()); dbClass = null; } return dbClass; } // end importClassFile()
public static String getTableName(@NonNull Object o) { Container container = ClassParser.getContainer(o.getClass()); String name = null; if (container != null) { name = getTableName(container); } return name; }
public static void main(String argv[]) { String[] file_name = new String[argv.length]; int files = 0; ClassParser parser = null; JavaClass java_class = null; String zip_file = null; char sep = System.getProperty("file.separator").toCharArray()[0]; String dir = "." + sep; // Where to store HTML files try { /* Parse command line arguments. */ for (int i = 0; i < argv.length; i++) { if (argv[i].charAt(0) == '-') { // command line switch if (argv[i].equals("-d")) { // Specify target directory, default `.� dir = argv[++i]; if (!dir.endsWith("" + sep)) dir = dir + sep; new File(dir).mkdirs(); // Create target directory if necessary } else if (argv[i].equals("-zip")) zip_file = argv[++i]; else System.out.println("Unknown option " + argv[i]); } else // add file name to list */ file_name[files++] = argv[i]; } if (files == 0) System.err.println("Class2HTML: No input files specified."); else { // Loop through files ... for (int i = 0; i < files; i++) { System.out.print("Processing " + file_name[i] + "..."); if (zip_file == null) parser = new ClassParser(file_name[i]); // Create parser object from file else parser = new ClassParser(zip_file, file_name[i]); // Create parser object from zip file java_class = parser.parse(); new Class2HTML(java_class, dir); System.out.println("Done."); } } } catch (Exception e) { System.out.println(e); e.printStackTrace(System.out); } }
/** * Given another class, return a transformed version of the class which replaces specified calls * with alternative static implementations */ public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { // debug = className.equals ("chicory/Test"); String fullClassName = className.replace("/", "."); debug_transform.log("In Transform: class = %s%n", className); // Don't instrument boot classes. We only want to instrument // user classes classpath. // Most boot classes have the null loader, // but some generated classes (such as those in sun.reflect) will // have a non-null loader. Some of these have a null parent loader, // but some do not. The check for the sun.reflect package is a hack // to catch all of these. A more consistent mechanism to determine // boot classes would be preferrable. if (loader == null) { debug_transform.log("ignoring system class %s, class loader == null", fullClassName); return (null); } else if (loader.getParent() == null) { debug_transform.log("ignoring system class %s, parent loader == null\n", fullClassName); return (null); } else if (fullClassName.startsWith("sun.reflect")) { debug_transform.log("ignoring system class %s, in sun.reflect package", fullClassName); return (null); } else if (fullClassName.startsWith("com.sun")) { System.out.printf("Class from com.sun package %s with nonnull loaders\n", fullClassName); } // Don't intrument our code if (className.startsWith("randoop.")) { debug_transform.log("Not considering randoop class %s%n", fullClassName); return (null); } // Look for match with specified regular expressions for class method_map = null; debug_class = false; for (MethodMapInfo mmi : map_list) { if (mmi.class_regex.matcher(className).matches()) { if (false && className.startsWith("RandoopTest")) debug_class = true; if (debug_class) System.out.printf("Classname %s matches re %s%n", className, mmi.class_regex); method_map = mmi.map; break; } } if (method_map == null) return null; debug_transform.log( "transforming class %s, loader %s - %s%n", className, loader, loader.getParent()); // Parse the bytes of the classfile, die on any errors JavaClass c = null; ClassParser parser = new ClassParser(new ByteArrayInputStream(classfileBuffer), className); try { c = parser.parse(); } catch (Exception e) { throw new RuntimeException("Unexpected error", e); } try { // Get the class information ClassGen cg = new ClassGen(c); ifact = new InstructionFactory(cg); map_calls(cg, className, loader); JavaClass njc = cg.getJavaClass(); if (debug) njc.dump("/tmp/ret/" + njc.getClassName() + ".class"); if (true) { return (cg.getJavaClass().getBytes()); } else { debug_transform.log("not including class %s (filtered out)", className); return null; } } catch (Throwable e) { out.format("Unexpected error %s in transform", e); e.printStackTrace(); return (null); } }
/** * Adds all the constants found in the given class into the given ConstantSet, and returns it. * * @see #getConstants(String) */ public static ConstantSet getConstants(String classname, ConstantSet result) { ClassParser cp; JavaClass jc; try { String classfileBase = classname.replace('.', '/'); InputStream is = ClassPath.SYSTEM_CLASS_PATH.getInputStream(classfileBase, ".class"); cp = new ClassParser(is, classname); jc = cp.parse(); } catch (java.io.IOException e) { throw new Error("IOException while reading '" + classname + "': " + e.getMessage()); } result.classname = jc.getClassName(); // Get all of the constants from the pool ConstantPool constant_pool = jc.getConstantPool(); for (Constant c : constant_pool.getConstantPool()) { // System.out.printf ("*Constant = %s%n", c); if (c == null || c instanceof ConstantClass || c instanceof ConstantFieldref || c instanceof ConstantInterfaceMethodref || c instanceof ConstantMethodref || c instanceof ConstantNameAndType || c instanceof ConstantUtf8) { continue; } if (c instanceof ConstantString) { result.strings.add((String) ((ConstantString) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantDouble) { result.doubles.add((Double) ((ConstantDouble) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantFloat) { result.floats.add((Float) ((ConstantFloat) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantInteger) { result.ints.add((Integer) ((ConstantInteger) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantLong) { result.longs.add((Long) ((ConstantLong) c).getConstantValue(constant_pool)); } else { throw new RuntimeException("Unrecognized constant of type " + c.getClass() + ": " + c); } } ClassGen gen = new ClassGen(jc); ConstantPoolGen pool = gen.getConstantPool(); // Process the code in each method looking for literals for (Method m : jc.getMethods()) { MethodGen mg = new MethodGen(m, jc.getClassName(), pool); InstructionList il = mg.getInstructionList(); if (il == null) { // System.out.println("No instructions for " + mg); } else { for (Instruction inst : il.getInstructions()) { switch (inst.getOpcode()) { // Compare two objects, no literals case Constants.IF_ACMPEQ: case Constants.IF_ACMPNE: break; // These instructions compare the integer on the top of the stack // to zero. There are no literals here (except 0) case Constants.IFEQ: case Constants.IFNE: case Constants.IFLT: case Constants.IFGE: case Constants.IFGT: case Constants.IFLE: { break; } // Instanceof pushes either 0 or 1 on the stack depending on whether // the object on top of stack is of the specified type. // If were interested in class literals, this would be interesting case Constants.INSTANCEOF: break; // Duplicates the item on the top of stack. No literal. case Constants.DUP: { break; } // Duplicates the item on the top of the stack and inserts it 2 // values down in the stack. No literals case Constants.DUP_X1: { break; } // Duplicates either the top 2 category 1 values or a single // category 2 value and inserts it 2 or 3 values down on the // stack. case Constants.DUP2_X1: { break; } // Duplicate either one category 2 value or two category 1 values. case Constants.DUP2: { break; } // Dup the category 1 value on the top of the stack and insert it either // two or three values down on the stack. case Constants.DUP_X2: { break; } case Constants.DUP2_X2: { break; } // Pop instructions discard the top of the stack. case Constants.POP: { break; } // Pops either the top 2 category 1 values or a single category 2 value // from the top of the stack. case Constants.POP2: { break; } // Swaps the two category 1 types on the top of the stack. case Constants.SWAP: { break; } // Compares two integers on the stack case Constants.IF_ICMPEQ: case Constants.IF_ICMPGE: case Constants.IF_ICMPGT: case Constants.IF_ICMPLE: case Constants.IF_ICMPLT: case Constants.IF_ICMPNE: { break; } // Get the value of a field case Constants.GETFIELD: { break; } // stores the top of stack into a field case Constants.PUTFIELD: { break; } // Pushes the value of a static field on the stack case Constants.GETSTATIC: { break; } // Pops a value off of the stack into a static field case Constants.PUTSTATIC: { break; } // pushes a local onto the stack case Constants.DLOAD: case Constants.DLOAD_0: case Constants.DLOAD_1: case Constants.DLOAD_2: case Constants.DLOAD_3: case Constants.FLOAD: case Constants.FLOAD_0: case Constants.FLOAD_1: case Constants.FLOAD_2: case Constants.FLOAD_3: case Constants.ILOAD: case Constants.ILOAD_0: case Constants.ILOAD_1: case Constants.ILOAD_2: case Constants.ILOAD_3: case Constants.LLOAD: case Constants.LLOAD_0: case Constants.LLOAD_1: case Constants.LLOAD_2: case Constants.LLOAD_3: { break; } // Pops a value off of the stack into a local case Constants.DSTORE: case Constants.DSTORE_0: case Constants.DSTORE_1: case Constants.DSTORE_2: case Constants.DSTORE_3: case Constants.FSTORE: case Constants.FSTORE_0: case Constants.FSTORE_1: case Constants.FSTORE_2: case Constants.FSTORE_3: case Constants.ISTORE: case Constants.ISTORE_0: case Constants.ISTORE_1: case Constants.ISTORE_2: case Constants.ISTORE_3: case Constants.LSTORE: case Constants.LSTORE_0: case Constants.LSTORE_1: case Constants.LSTORE_2: case Constants.LSTORE_3: { break; } // Push a value from the runtime constant pool. We'll get these // values when processing the constant pool itself case Constants.LDC: case Constants.LDC_W: case Constants.LDC2_W: { break; } // Push the length of an array on the stack case Constants.ARRAYLENGTH: { break; } // Push small constants (-1..5) on the stack. These literals are // too common to bother mentioning case Constants.DCONST_0: case Constants.DCONST_1: case Constants.FCONST_0: case Constants.FCONST_1: case Constants.FCONST_2: case Constants.ICONST_0: case Constants.ICONST_1: case Constants.ICONST_2: case Constants.ICONST_3: case Constants.ICONST_4: case Constants.ICONST_5: case Constants.ICONST_M1: case Constants.LCONST_0: case Constants.LCONST_1: { break; } case Constants.BIPUSH: case Constants.SIPUSH: { ConstantPushInstruction cpi = (ConstantPushInstruction) inst; result.ints.add((Integer) cpi.getValue()); break; } // Primitive Binary operators. case Constants.DADD: case Constants.DCMPG: case Constants.DCMPL: case Constants.DDIV: case Constants.DMUL: case Constants.DREM: case Constants.DSUB: case Constants.FADD: case Constants.FCMPG: case Constants.FCMPL: case Constants.FDIV: case Constants.FMUL: case Constants.FREM: case Constants.FSUB: case Constants.IADD: case Constants.IAND: case Constants.IDIV: case Constants.IMUL: case Constants.IOR: case Constants.IREM: case Constants.ISHL: case Constants.ISHR: case Constants.ISUB: case Constants.IUSHR: case Constants.IXOR: case Constants.LADD: case Constants.LAND: case Constants.LCMP: case Constants.LDIV: case Constants.LMUL: case Constants.LOR: case Constants.LREM: case Constants.LSHL: case Constants.LSHR: case Constants.LSUB: case Constants.LUSHR: case Constants.LXOR: break; case Constants.LOOKUPSWITCH: case Constants.TABLESWITCH: break; case Constants.ANEWARRAY: case Constants.NEWARRAY: { break; } case Constants.MULTIANEWARRAY: { break; } // push the value at an index in an array case Constants.AALOAD: case Constants.BALOAD: case Constants.CALOAD: case Constants.DALOAD: case Constants.FALOAD: case Constants.IALOAD: case Constants.LALOAD: case Constants.SALOAD: { break; } // Pop the top of stack into an array location case Constants.AASTORE: case Constants.BASTORE: case Constants.CASTORE: case Constants.DASTORE: case Constants.FASTORE: case Constants.IASTORE: case Constants.LASTORE: case Constants.SASTORE: break; case Constants.ARETURN: case Constants.DRETURN: case Constants.FRETURN: case Constants.IRETURN: case Constants.LRETURN: case Constants.RETURN: { break; } // subroutine calls. case Constants.INVOKESTATIC: case Constants.INVOKEVIRTUAL: case Constants.INVOKESPECIAL: case Constants.INVOKEINTERFACE: break; // Throws an exception. case Constants.ATHROW: break; // Opcodes that don't need any modifications. Here for reference case Constants.ACONST_NULL: case Constants.ALOAD: case Constants.ALOAD_0: case Constants.ALOAD_1: case Constants.ALOAD_2: case Constants.ALOAD_3: case Constants.ASTORE: case Constants.ASTORE_0: case Constants.ASTORE_1: case Constants.ASTORE_2: case Constants.ASTORE_3: case Constants.CHECKCAST: case Constants.D2F: // double to float case Constants.D2I: // double to integer case Constants.D2L: // double to long case Constants.DNEG: // Negate double on top of stack case Constants.F2D: // float to double case Constants.F2I: // float to integer case Constants.F2L: // float to long case Constants.FNEG: // Negate float on top of stack case Constants.GOTO: case Constants.GOTO_W: case Constants.I2B: // integer to byte case Constants.I2C: // integer to char case Constants.I2D: // integer to double case Constants.I2F: // integer to float case Constants.I2L: // integer to long case Constants.I2S: // integer to short case Constants.IFNONNULL: case Constants.IFNULL: case Constants.IINC: // increment local variable by a constant case Constants.INEG: // negate integer on top of stack case Constants.JSR: // pushes return address on the stack, case Constants.JSR_W: case Constants.L2D: // long to double case Constants.L2F: // long to float case Constants.L2I: // long to int case Constants.LNEG: // negate long on top of stack case Constants.MONITORENTER: case Constants.MONITOREXIT: case Constants.NEW: case Constants.NOP: case Constants.RET: // this is the internal JSR return break; // Make sure we didn't miss anything default: throw new Error("instruction " + inst + " unsupported"); } } } } return result; }
/* * (non-Javadoc) * * @see * edu.umd.cs.findbugs.classfile.engine.ClassParserInterface#parse(edu.umd * .cs.findbugs.classfile.analysis.ClassNameAndSuperclassInfo.Builder) */ public void parse(final ClassNameAndSuperclassInfo.Builder cBuilder) throws InvalidClassFileFormatException { cBuilder.setCodeBaseEntry(codeBaseEntry); final TreeSet<ClassDescriptor> calledClassSet = new TreeSet<ClassDescriptor>(); classReader.accept( new ClassVisitor() { boolean isInnerClass = false; public void visit( int version, int access, String name, String signature, String superName, String[] interfaces) { ClassParserUsingASM.this.slashedClassName = name; cBuilder.setClassfileVersion(version >>> 16, version & 0xffff); cBuilder.setAccessFlags(access); cBuilder.setClassDescriptor(DescriptorFactory.createClassDescriptor(name)); cBuilder.setInterfaceDescriptorList( DescriptorFactory.createClassDescriptor(interfaces)); if (superName != null) cBuilder.setSuperclassDescriptor(DescriptorFactory.createClassDescriptor(superName)); if (cBuilder instanceof ClassInfo.Builder) { ((ClassInfo.Builder) cBuilder).setSourceSignature(signature); } } public org.objectweb.asm.AnnotationVisitor visitAnnotation( String desc, boolean isVisible) { if (cBuilder instanceof ClassInfo.Builder) { AnnotationValue value = new AnnotationValue(desc); ((ClassInfo.Builder) cBuilder).addAnnotation(desc, value); return value.getAnnotationVisitor(); } return null; } public void visitAttribute(Attribute arg0) { // TODO Auto-generated method stub } public void visitEnd() { // TODO Auto-generated method stub } public FieldVisitor visitField( int access, String name, String desc, String signature, Object value) { if (name.equals("this$0")) isInnerClass = true; if (desc == null) throw new NullPointerException("Description cannot be null"); if (cBuilder instanceof ClassInfo.Builder) { final ClassInfo.Builder cBuilder2 = (ClassInfo.Builder) cBuilder; if ((access & Opcodes.ACC_VOLATILE) != 0 || desc.contains("util/concurrent")) cBuilder2.setUsesConcurrency(); final FieldInfo.Builder fBuilder = new FieldInfo.Builder(slashedClassName, name, desc, access); fBuilder.setSourceSignature(signature); return new AbstractFieldAnnotationVisitor() { public org.objectweb.asm.AnnotationVisitor visitAnnotation( final String desc, boolean visible) { AnnotationValue value = new AnnotationValue(desc); fBuilder.addAnnotation(desc, value); return value.getAnnotationVisitor(); } public void visitEnd() { cBuilder2.addFieldDescriptor(fBuilder.build()); } }; } return null; } public void visitInnerClass(String name, String outerName, String innerName, int access) { if (name.equals(slashedClassName) && outerName != null) { if (cBuilder instanceof ClassInfo.Builder) { ClassDescriptor outerClassDescriptor = DescriptorFactory.createClassDescriptor(outerName); ((ClassInfo.Builder) cBuilder).setImmediateEnclosingClass(outerClassDescriptor); ((ClassInfo.Builder) cBuilder).setAccessFlags(access); } } } public MethodVisitor visitMethod( final int access, final String methodName, final String methodDesc, String signature, String[] exceptions) { if (cBuilder instanceof ClassInfo.Builder) { final MethodInfo.Builder mBuilder = new MethodInfo.Builder(slashedClassName, methodName, methodDesc, access); mBuilder.setSourceSignature(signature); mBuilder.setThrownExceptions(exceptions); if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) mBuilder.setUsesConcurrency(); return new AbstractMethodVisitor() { int variable; boolean sawReturn = (access & Opcodes.ACC_NATIVE) != 0; boolean sawNormalThrow = false; boolean sawUnsupportedThrow = false; boolean sawSystemExit = false; boolean sawBranch = false; boolean sawBackBranch = false; int methodCallCount = 0; boolean sawStubThrow = false; boolean justSawInitializationOfUnsupportedOperationException; boolean isBridge = (access & Opcodes.ACC_SYNTHETIC) != 0 && (access & Opcodes.ACC_BRIDGE) != 0; String bridgedMethodSignature; State state = State.INITIAL; StubState stubState = StubState.INITIAL; boolean isAccessMethod = methodName.startsWith("access$"); String accessOwner, accessName, accessDesc; boolean accessIsStatic; HashSet<Label> labelsSeen = new HashSet<Label>(); @Override public void visitLdcInsn(Object cst) { if (cst.equals("Stub!")) stubState = StubState.LOADED_STUB; else stubState = StubState.INITIAL; } @Override public void visitInsn(int opcode) { if (opcode == Opcodes.MONITORENTER) mBuilder.setUsesConcurrency(); if (RETURN_OPCODE_SET.get(opcode)) sawReturn = true; else if (opcode == Opcodes.ATHROW) { if (stubState == StubState.INITIALIZE_RUNTIME) { sawStubThrow = true; } else if (justSawInitializationOfUnsupportedOperationException) sawUnsupportedThrow = true; else sawNormalThrow = true; } resetState(); } public void resetState() { if (state != State.AFTER_METHOD_CALL) state = State.INITIAL; stubState = StubState.INITIAL; } @Override public void visitSomeInsn() { resetState(); } @Override public void visitVarInsn(int opcode, int var) { if (opcode == Opcodes.ALOAD && var == 0) state = State.THIS_LOADED; else if (state == State.THIS_LOADED) switch (opcode) { case Opcodes.ALOAD: case Opcodes.ILOAD: case Opcodes.LLOAD: case Opcodes.DLOAD: case Opcodes.FLOAD: state = State.VARIABLE_LOADED; variable = var; } else visitSomeInsn(); } public org.objectweb.asm.AnnotationVisitor visitAnnotation( final String desc, boolean visible) { AnnotationValue value = new AnnotationValue(desc); mBuilder.addAnnotation(desc, value); return value.getAnnotationVisitor(); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { methodCallCount++; if (isAccessMethod && methodCallCount == 1) { this.accessOwner = owner; this.accessName = name; this.accessDesc = desc; this.accessIsStatic = opcode == Opcodes.INVOKESTATIC; } if (stubState == StubState.LOADED_STUB && opcode == Opcodes.INVOKESPECIAL && owner.equals("java/lang/RuntimeException") && name.equals("<init>")) stubState = StubState.INITIALIZE_RUNTIME; else stubState = StubState.INITIAL; if (owner.startsWith("java/util/concurrent")) mBuilder.setUsesConcurrency(); if (opcode == Opcodes.INVOKEINTERFACE) return; if (owner.charAt(0) == '[' && owner.charAt(owner.length() - 1) != ';') { // primitive array return; } if (opcode == Opcodes.INVOKESTATIC && owner.equals("java/lang/System") && name.equals("exit") && !sawReturn) sawSystemExit = true; justSawInitializationOfUnsupportedOperationException = opcode == Opcodes.INVOKESPECIAL && owner.equals("java/lang/UnsupportedOperationException") && name.equals("<init>"); if (isBridge && bridgedMethodSignature == null) switch (opcode) { case Opcodes.INVOKEVIRTUAL: case Opcodes.INVOKESPECIAL: case Opcodes.INVOKESTATIC: case Opcodes.INVOKEINTERFACE: if (desc != null && name.equals(methodName)) bridgedMethodSignature = desc; } // System.out.println("Call from " + // ClassParserUsingASM.this.slashedClassName + // " to " + owner + " : " + desc); if (desc == null || desc.indexOf('[') == -1 && desc.indexOf('L') == -1) return; if (ClassParserUsingASM.this.slashedClassName.equals(owner)) return; ClassDescriptor classDescriptor = DescriptorFactory.instance().getClassDescriptor(owner); calledClassSet.add(classDescriptor); // System.out.println("Added call from " + // ClassParserUsingASM.this.slashedClassName + // " to " + owner); state = State.AFTER_METHOD_CALL; } @Override public void visitJumpInsn(int opcode, Label label) { sawBranch = true; if (labelsSeen.contains(label)) sawBackBranch = true; super.visitJumpInsn(opcode, label); } @Override public void visitLabel(Label label) { labelsSeen.add(label); super.visitLabel(label); } public void visitEnd() { labelsSeen.clear(); if (isAccessMethod && methodCallCount == 1) { mBuilder.setAccessMethodFor( accessOwner, accessName, accessDesc, accessIsStatic); } if (sawBackBranch) mBuilder.setHasBackBranch(); boolean sawThrow = sawNormalThrow | sawUnsupportedThrow | sawStubThrow; if (sawThrow && !sawReturn || sawSystemExit && !sawBranch) { mBuilder.setIsUnconditionalThrower(); if (!sawReturn && !sawNormalThrow) { if (sawUnsupportedThrow) mBuilder.setUnsupported(); if (sawStubThrow) { mBuilder.addAccessFlags(Constants.ACC_SYNTHETIC); mBuilder.setIsStub(); } } // else // System.out.println(slashedClassName+"."+methodName+methodDesc // + " is thrower"); } mBuilder.setNumberMethodCalls(methodCallCount); MethodInfo methodInfo = mBuilder.build(); Builder classBuilder = (ClassInfo.Builder) cBuilder; if (isBridge && bridgedMethodSignature != null && !bridgedMethodSignature.equals(methodDesc)) classBuilder.addBridgeMethodDescriptor(methodInfo, bridgedMethodSignature); else classBuilder.addMethodDescriptor(methodInfo); if (methodInfo.usesConcurrency()) classBuilder.setUsesConcurrency(); if (methodInfo.isStub()) classBuilder.setHasStubs(); } public org.objectweb.asm.AnnotationVisitor visitParameterAnnotation( int parameter, String desc, boolean visible) { AnnotationValue value = new AnnotationValue(desc); mBuilder.addParameterAnnotation(parameter, desc, value); return value.getAnnotationVisitor(); } }; } return null; } public void visitOuterClass(String owner, String name, String desc) {} public void visitSource(String arg0, String arg1) { if (cBuilder instanceof ClassInfo.Builder) { ((ClassInfo.Builder) cBuilder).setSource(arg0); } } }, ClassReader.SKIP_FRAMES); HashSet<ClassDescriptor> referencedClassSet = new HashSet<ClassDescriptor>(); // collect class references int constantPoolCount = classReader.readUnsignedShort(8); int offset = 10; char[] buf = new char[1024]; // System.out.println("constant pool count: " + constantPoolCount); for (int count = 1; count < constantPoolCount; count++) { int tag = classReader.readByte(offset); int size; switch (tag) { case Constants.CONSTANT_Methodref: case Constants.CONSTANT_InterfaceMethodref: case Constants.CONSTANT_Fieldref: case Constants.CONSTANT_Integer: case Constants.CONSTANT_Float: case Constants.CONSTANT_NameAndType: size = 5; break; case Constants.CONSTANT_Long: case Constants.CONSTANT_Double: size = 9; count++; break; case Constants.CONSTANT_Utf8: size = 3 + classReader.readUnsignedShort(offset + 1); break; case Constants.CONSTANT_Class: @SlashedClassName String className = classReader.readUTF8(offset + 1, buf); if (className.indexOf('[') >= 0) { ClassParser.extractReferencedClassesFromSignature(referencedClassSet, className); } else if (ClassName.isValidClassName(className)) { ClassDescriptor classDescriptor = DescriptorFactory.instance().getClassDescriptor(className); referencedClassSet.add(classDescriptor); } size = 3; break; // case ClassWriter.CLASS: // case ClassWriter.STR: case Constants.CONSTANT_String: size = 3; break; default: throw new IllegalStateException( "Unexpected tag of " + tag + " at offset " + offset + " while parsing " + slashedClassName + " from " + codeBaseEntry); } // System.out.println(count + "@" + offset + " : [" + tag // +"] size="+size); offset += size; } cBuilder.setCalledClassDescriptors(calledClassSet); cBuilder.setReferencedClassDescriptors(referencedClassSet); }