/** @return Resolved string representation */ public final String toString(ConstantPool constant_pool) { String inner_class_name, outer_class_name, inner_name, access; inner_class_name = constant_pool.getConstantString(inner_class_index, Constants.CONSTANT_Class); inner_class_name = Utility.compactClassName(inner_class_name); if (outer_class_index != 0) { outer_class_name = constant_pool.getConstantString(outer_class_index, Constants.CONSTANT_Class); outer_class_name = Utility.compactClassName(outer_class_name); } else { outer_class_name = "<not a member>"; } if (inner_name_index != 0) { inner_name = ((ConstantUtf8) constant_pool.getConstant(inner_name_index, Constants.CONSTANT_Utf8)) .getBytes(); } else { inner_name = "<anonymous>"; } access = Utility.accessToString(inner_access_flags, true); access = access.equals("") ? "" : (access + " "); return "InnerClass:" + access + inner_class_name + "(\"" + outer_class_name + "\", \"" + inner_name + "\")"; }
/** * 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; }
public void visitConstantPool(ConstantPool cp) { cp.accept(visitor); Constant[] constants = cp.getConstantPool(); for (int i = 1; i < constants.length; i++) { if (constants[i] != null) constants[i].accept(this); } }
public void visitOuterClass(final String owner, final String name, final String desc) { cp.newUTF8("EnclosingMethod"); cp.newClass(owner); if (name != null && desc != null) { cp.newNameType(name, desc); } cv.visitOuterClass(owner, name, desc); }
@Override public void visitParameter(String name, int access) { cp.newUTF8("MethodParameters"); if (name != null) { cp.newUTF8(name); } mv.visitParameter(name, access); }
public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { cp.newUTF8(desc); if (visible) { cp.newUTF8("RuntimeVisibleAnnotations"); } else { cp.newUTF8("RuntimeInvisibleAnnotations"); } return new AnnotationConstantsCollector(cv.visitAnnotation(desc, visible), cp); }
private int getOrInsertMethodRef(int classIndex, int nameAndTypeIndex) throws IOException { int methodRef = constantPool.lookForRef(classIndex, nameAndTypeIndex); if (methodRef == -1) { methodRef = constantPool.poolSize() + 1; MethodRefConstant methodRefConstant = new MethodRefConstant(classIndex, nameAndTypeIndex); constantPool.add(methodRefConstant); methodRefConstant.serializeToStream(constantStream); } return methodRef; }
private int getOrInsertUtf8(String string) throws IOException { int nameIndex = constantPool.lookForUtf8Reference(string); if (nameIndex == -1) { nameIndex = constantPool.poolSize() + 1; Utf8Constant name = new Utf8Constant(string); constantPool.add(name); name.serializeToStream(constantStream); } return nameIndex; }
public void visitSource(final String source, final String debug) { if (source != null) { cp.newUTF8("SourceFile"); cp.newUTF8(source); } if (debug != null) { cp.newUTF8("SourceDebugExtension"); } cv.visitSource(source, debug); }
private int getOrInsertString(int utf8Index) throws IOException { int stringIndex = constantPool.lookForString(utf8Index); if (stringIndex == -1) { stringIndex = constantPool.poolSize() + 1; StringConstant stringConstant = new StringConstant(utf8Index); constantPool.add(stringConstant); stringConstant.serializeToStream(constantStream); } return stringIndex; }
private int getOrInsertNameAndType(int nameIndex, int typeIndex) throws IOException { int nameAndTypeIndex = constantPool.lookForNameAndTypeReference(nameIndex, typeIndex); if (nameAndTypeIndex == -1) { nameAndTypeIndex = constantPool.poolSize() + 1; NameAndTypeConstant nameAndType = new NameAndTypeConstant(nameIndex, typeIndex); constantPool.add(nameAndType); nameAndType.serializeToStream(constantStream); } return nameAndTypeIndex; }
private int getOrInsertClass(int nameIndex) throws IOException { int classIndex = constantPool.lookForClass(nameIndex); if (classIndex == -1) { classIndex = constantPool.poolSize() + 1; ClassConstant classConstant = new ClassConstant(nameIndex); constantPool.add(classConstant); classConstant.serializeToStream(constantStream); } return classIndex; }
@Override public AnnotationVisitor visitTypeAnnotation( int typeRef, TypePath typePath, String desc, boolean visible) { cp.newUTF8(desc); if (visible) { cp.newUTF8("RuntimeVisibleTypeAnnotations"); } else { cp.newUTF8("RuntimeInvisibleTypeAnnotations"); } return new AnnotationConstantsCollector(mv.visitAnnotation(desc, visible), cp); }
public AnnotationVisitor visitParameterAnnotation( final int parameter, final String desc, final boolean visible) { cp.newUTF8(desc); if (visible) { cp.newUTF8("RuntimeVisibleParameterAnnotations"); } else { cp.newUTF8("RuntimeInvisibleParameterAnnotations"); } return new AnnotationConstantsCollector( mv.visitParameterAnnotation(parameter, desc, visible), cp); }
public void visitInnerClass( final String name, final String outerName, final String innerName, final int access) { cp.newUTF8("InnerClasses"); if (name != null) { cp.newClass(name); } if (outerName != null) { cp.newClass(outerName); } if (innerName != null) { cp.newUTF8(innerName); } cv.visitInnerClass(name, outerName, innerName, access); }
public void visitTryCatchBlock( final Label start, final Label end, final Label handler, final String type) { if (type != null) { cp.newClass(type); } mv.visitTryCatchBlock(start, end, handler, type); }
ConstantHTML( String dir, String class_name, String class_package, Method[] methods, ConstantPool constant_pool) throws IOException { this.class_name = class_name; this.class_package = class_package; this.constant_pool = constant_pool; this.methods = methods; constants = constant_pool.getConstantPool(); file = new PrintWriter(new FileOutputStream(dir + class_name + "_cp.html")); constant_ref = new String[constants.length]; constant_ref[0] = "<unknown>"; file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>"); // Loop through constants, constants[0] is reserved for (int i = 1; i < constants.length; i++) { if (i % 2 == 0) file.print("<TR BGCOLOR=\"#C0C0C0\"><TD>"); else file.print("<TR BGCOLOR=\"#A0A0A0\"><TD>"); if (constants[i] != null) writeConstant(i); file.print("</TD></TR>\n"); } file.println("</TABLE></BODY></HTML>"); file.close(); }
/** * Resolve this constant pool entry with respect to its dependents in the constant pool. * * @param constantPool the constant pool of which this entry is a member and against which this * entry is to be resolved. */ @Override public void resolve(final ConstantPool constantPool) { final Utf8CPInfo methodClass = (Utf8CPInfo) constantPool.getEntry(methodDescriptorIndex); methodClass.resolve(constantPool); methodDescriptor = methodClass.getValue(); super.resolve(constantPool); }
/** * Create a non-standard attribute. * * @param name_index Index in constant pool * @param length Content length in bytes * @param bytes Attribute contents * @param constant_pool Array of constants */ public Unknown(int name_index, int length, byte[] bytes, ConstantPool constant_pool) { super(Constants.ATTR_UNKNOWN, name_index, length, constant_pool); this.bytes = bytes; name = ((ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8)).getBytes(); unknown_attributes.put(name, this); }
private MethodInfo readMethod() throws IOException { MethodInfo methodInfo = new MethodInfo(); methodInfo.setAccessFlags(is.readUnsignedShort()); methodInfo.setNameIndex(is.readUnsignedShort()); methodInfo.setDescriptorIndex(is.readUnsignedShort()); int attributesCount = is.readUnsignedShort(); methodInfo.setAttributes(new AbstractAttribute[attributesCount]); for (int i = 0; i < attributesCount; i++) { AbstractAttribute attribute = attributeFacility.readAttribute(); if (isInterceptorAnnotation(attribute)) { methodInfo.setInterceptorClass( ((RuntimeInvisibleAnnotations) attribute).getInterceptorClass()); } methodInfo.getAttributes()[i] = attribute; if (attribute.getClass() == Code.class) { methodInfo.setCode((Code) attribute); } } methodInfo.setSignature(getMethodSignature(methodInfo)); methodInfo.setMethodName(constantPool.getUtf8(methodInfo.getNameIndex()).getString()); return methodInfo; }
@Override public void visitMethodInsn( final int opcode, final String owner, final String name, final String desc) { boolean itf = opcode == Opcodes.INVOKEINTERFACE; cp.newMethod(owner, name, desc, itf); mv.visitMethodInsn(opcode, owner, name, desc); }
/** Parses an {@code InnerClasses} attribute. */ private Attribute innerClasses( DirectClassFile cf, int offset, int length, ParseObserver observer) { if (length < 2) { return throwSeverelyTruncated(); } ByteArray bytes = cf.getBytes(); ConstantPool pool = cf.getConstantPool(); int count = bytes.getUnsignedShort(offset); // number_of_classes if (observer != null) { observer.parsed(bytes, offset, 2, "number_of_classes: " + Hex.u2(count)); } offset += 2; length -= 2; if (length != (count * 8)) { throwBadLength((count * 8) + 2); } InnerClassList list = new InnerClassList(count); for (int i = 0; i < count; i++) { int innerClassIdx = bytes.getUnsignedShort(offset); int outerClassIdx = bytes.getUnsignedShort(offset + 2); int nameIdx = bytes.getUnsignedShort(offset + 4); int accessFlags = bytes.getUnsignedShort(offset + 6); CstType innerClass = (CstType) pool.get(innerClassIdx); CstType outerClass = (CstType) pool.get0Ok(outerClassIdx); CstString name = (CstString) pool.get0Ok(nameIdx); list.set(i, innerClass, outerClass, name, accessFlags); if (observer != null) { observer.parsed( bytes, offset, 2, "inner_class: " + DirectClassFile.stringOrNone(innerClass)); observer.parsed( bytes, offset + 2, 2, " outer_class: " + DirectClassFile.stringOrNone(outerClass)); observer.parsed(bytes, offset + 4, 2, " name: " + DirectClassFile.stringOrNone(name)); observer.parsed( bytes, offset + 6, 2, " access_flags: " + AccessFlags.innerClassString(accessFlags)); } offset += 8; } list.setImmutable(); return new AttInnerClasses(list); }
/** Parses a {@code SourceFile} attribute. */ private Attribute sourceFile(DirectClassFile cf, int offset, int length, ParseObserver observer) { if (length != 2) { throwBadLength(2); } ByteArray bytes = cf.getBytes(); ConstantPool pool = cf.getConstantPool(); int idx = bytes.getUnsignedShort(offset); CstString cst = (CstString) pool.get(idx); Attribute result = new AttSourceFile(cst); if (observer != null) { observer.parsed(bytes, offset, 2, "source: " + cst); } return result; }
public void visitLocalVariable( final String name, final String desc, final String signature, final Label start, final Label end, final int index) { if (signature != null) { cp.newUTF8("LocalVariableTypeTable"); cp.newUTF8(name); cp.newUTF8(signature); } cp.newUTF8("LocalVariableTable"); cp.newUTF8(name); cp.newUTF8(desc); mv.visitLocalVariable(name, desc, signature, start, end, index); }
public void visit( final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { if ((access & Opcodes.ACC_DEPRECATED) != 0) { cp.newUTF8("Deprecated"); } if ((access & Opcodes.ACC_SYNTHETIC) != 0) { cp.newUTF8("Synthetic"); } cp.newClass(name); if (signature != null) { cp.newUTF8("Signature"); cp.newUTF8(signature); } if (superName != null) { cp.newClass(superName); } if (interfaces != null) { for (int i = 0; i < interfaces.length; ++i) { cp.newClass(interfaces[i]); } } cv.visit(version, access, name, signature, superName, interfaces); }
public MethodVisitor visitMethod( final int access, final String name, final String desc, final String signature, final String[] exceptions) { if ((access & Opcodes.ACC_SYNTHETIC) != 0) { cp.newUTF8("Synthetic"); } if ((access & Opcodes.ACC_DEPRECATED) != 0) { cp.newUTF8("Deprecated"); } cp.newUTF8(name); cp.newUTF8(desc); if (signature != null) { cp.newUTF8("Signature"); cp.newUTF8(signature); } if (exceptions != null) { cp.newUTF8("Exceptions"); for (int i = 0; i < exceptions.length; ++i) { cp.newClass(exceptions[i]); } } return new MethodConstantsCollector( cv.visitMethod(access, name, desc, signature, exceptions), cp); }
static void optimize(final File f, final File d, final Remapper remapper) throws IOException { if (f.isDirectory()) { File[] files = f.listFiles(); for (int i = 0; i < files.length; ++i) { optimize(files[i], d, remapper); } } else if (f.getName().endsWith(".class")) { ConstantPool cp = new ConstantPool(); ClassReader cr = new ClassReader(new FileInputStream(f)); // auto-boxing removal requires to recompute the maxs ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassConstantsCollector ccc = new ClassConstantsCollector(cw, cp); ClassOptimizer co = new ClassOptimizer(ccc, remapper); cr.accept(co, ClassReader.SKIP_DEBUG); Set<Constant> constants = new TreeSet<Constant>(new ConstantComparator()); constants.addAll(cp.values()); cr = new ClassReader(cw.toByteArray()); cw = new ClassWriter(0); Iterator<Constant> i = constants.iterator(); while (i.hasNext()) { Constant c = i.next(); c.write(cw); } cr.accept(cw, ClassReader.SKIP_DEBUG); if (MAPPING.get(cr.getClassName() + "/remove") != null) { return; } String n = remapper.mapType(cr.getClassName()); File g = new File(d, n + ".class"); if (!g.exists() || g.lastModified() < f.lastModified()) { if (!g.getParentFile().exists() && !g.getParentFile().mkdirs()) { throw new IOException("Cannot create directory " + g.getParentFile()); } OutputStream os = new FileOutputStream(g); try { os.write(cw.toByteArray()); } finally { os.close(); } } } }
/** Parses a {@code ConstantValue} attribute. */ private Attribute constantValue( DirectClassFile cf, int offset, int length, ParseObserver observer) { if (length != 2) { return throwBadLength(2); } ByteArray bytes = cf.getBytes(); ConstantPool pool = cf.getConstantPool(); int idx = bytes.getUnsignedShort(offset); TypedConstant cst = (TypedConstant) pool.get(idx); Attribute result = new AttConstantValue(cst); if (observer != null) { observer.parsed(bytes, offset, 2, "value: " + cst); } return result; }
@Override public AnnotationVisitor visitLocalVariableAnnotation( int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { cp.newUTF8(desc); if (visible) { cp.newUTF8("RuntimeVisibleTypeAnnotations"); } else { cp.newUTF8("RuntimeInvisibleTypeAnnotations"); } return new AnnotationConstantsCollector( mv.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, desc, visible), cp); }
/** Collect all constants into the constant table */ public void collect(Environment env, MemberDefinition field, ConstantPool tab) { // Collect constants for arguments only // if a local variable table is generated if ((field != null) && env.debug_vars()) { if (field.getArguments() != null) { for (Enumeration e = field.getArguments().elements(); e.hasMoreElements(); ) { MemberDefinition f = (MemberDefinition) e.nextElement(); tab.put(f.getName().toString()); tab.put(f.getType().getTypeSignature()); } } } // Collect constants from the instructions for (Instruction inst = first; inst != null; inst = inst.next) { inst.collect(tab); } }