@Override public final void visitSource(final String file, final String debug) { if (file != null) { sourceFile = newUTF8(file); } if (debug != null) { sourceDebug = new ByteVector().encodeUTF8(debug, 0, Integer.MAX_VALUE); } }
/** * Adds a name and type to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. * * @param name * a name. * @param desc * a type descriptor. * @return a new or already existing name and type item. */ Item newNameTypeItem(final String name, final String desc) { key2.set(NAME_TYPE, name, desc, null); Item result = get(key2); if (result == null) { put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); result = new Item(index++, key2); put(result); } return result; }
@Override public final void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { this.version = version; this.access = access; this.name = newClass(name); thisName = name; if (ClassReader.SIGNATURES && signature != null) { this.signature = newUTF8(signature); } this.superName = superName == null ? 0 : newClass(superName); if (interfaces != null && interfaces.length > 0) { interfaceCount = interfaces.length; this.interfaces = new int[interfaceCount]; for (int i = 0; i < interfaceCount; ++i) { this.interfaces[i] = newClass(interfaces[i]); } } }
@Override public final AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } ByteVector bv = new ByteVector(); // write type, and reserve space for values count bv.putShort(newUTF8(desc)).putShort(0); AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); if (visible) { aw.next = anns; anns = aw; } else { aw.next = ianns; ianns = aw; } return aw; }
/** * Adds a class reference to the constant pool of the class being build. * Does nothing if the constant pool already contains a similar item. * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * * @param value * the internal name of the class. * @return a new or already existing class reference item. */ Item newClassItem(final String value) { key2.set(CLASS, value, null, null); Item result = get(key2); if (result == null) { pool.put12(CLASS, newUTF8(value)); result = new Item(index++, key2); put(result); } return result; }
/** * Adds a string to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * * @param value * the String value. * @return a new or already existing string item. */ private Item newString(final String value) { key2.set(STR, value, null, null); Item result = get(key2); if (result == null) { pool.put12(STR, newUTF8(value)); result = new Item(index++, key2); put(result); } return result; }
/** * Adds a method type reference to the constant pool of the class being * build. Does nothing if the constant pool already contains a similar item. * <i>This method is intended for {@link Attribute} sub classes, and is * normally not needed by class generators or adapters.</i> * * @param methodDesc * method descriptor of the method type. * @return a new or already existing method type reference item. */ Item newMethodTypeItem(final String methodDesc) { key2.set(MTYPE, methodDesc, null, null); Item result = get(key2); if (result == null) { pool.put12(MTYPE, newUTF8(methodDesc)); result = new Item(index++, key2); put(result); } return result; }
newUTF8("BootstrapMethods"); newUTF8("Signature"); newUTF8("SourceFile"); newUTF8("SourceDebugExtension"); newUTF8("EnclosingMethod"); newUTF8("Deprecated"); ++attributeCount; size += 6; newUTF8("Synthetic"); ++attributeCount; size += 8 + innerClasses.length; newUTF8("InnerClasses"); newUTF8("RuntimeVisibleAnnotations"); newUTF8("RuntimeInvisibleAnnotations"); newUTF8("RuntimeVisibleTypeAnnotations"); newUTF8("RuntimeInvisibleTypeAnnotations"); out.putShort(newUTF8("BootstrapMethods"));
@Override public final AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, final String desc, final boolean visible) { if (!ClassReader.ANNOTATIONS) { return null; } ByteVector bv = new ByteVector(); // write target_type and target_info AnnotationWriter.putTarget(typeRef, typePath, bv); // write type, and reserve space for values count bv.putShort(newUTF8(desc)).putShort(0); AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, bv.length - 2); if (visible) { aw.next = tanns; tanns = aw; } else { aw.next = itanns; itanns = aw; } return aw; }
@Override public final void visitInnerClass(final String name, final String outerName, final String innerName, final int access) { if (innerClasses == null) { innerClasses = new ByteVector(); } // Sec. 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the // constant_pool table which represents a class or interface C that is // not a package member must have exactly one corresponding entry in the // classes array". To avoid duplicates we keep track in the intVal field // of the Item of each CONSTANT_Class_info entry C whether an inner // class entry has already been added for C (this field is unused for // class entries, and changing its value does not change the hashcode // and equality tests). If so we store the index of this inner class // entry (plus one) in intVal. This hack allows duplicate detection in // O(1) time. Item nameItem = newClassItem(name); if (nameItem.intVal == 0) { ++innerClassesCount; innerClasses.putShort(nameItem.index); innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); innerClasses.putShort(access); nameItem.intVal = innerClassesCount; } else { // Compare the inner classes entry nameItem.intVal - 1 with the // arguments of this method and throw an exception if there is a // difference? } }