@Override public void visitNestHost(final String nestHost) { nestHostClassIndex = symbolTable.addConstantClass(nestHost).index; }
/** * Sets the major version and the name of the class to which this symbol table belongs. Also adds * the class name to the constant pool. * * @param majorVersion a major ClassFile version number. * @param className an internal class name. * @return the constant pool index of a new or already existing Symbol with the given class name. */ int setMajorVersionAndClassName(final int majorVersion, final String className) { this.majorVersion = majorVersion; this.className = className; return addConstantClass(className).index; }
/** * 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 the index of a new or already existing class reference item. */ public int newClass(final String value) { return symbolTable.addConstantClass(value).index; }
@Override public void visitMainClass(final String mainClass) { this.mainClassIndex = symbolTable.addConstantClass(mainClass).index; }
@Override public final void visitOuterClass( final String owner, final String name, final String descriptor) { enclosingClassIndex = symbolTable.addConstantClass(owner).index; if (name != null && descriptor != null) { enclosingMethodIndex = symbolTable.addConstantNameAndType(name, descriptor); } }
@Override public void visitUse(final String service) { usesIndex.putShort(symbolTable.addConstantClass(service).index); usesCount++; }
@Override public void visitTryCatchBlock( final Label start, final Label end, final Label handler, final String type) { Handler newHandler = new Handler( start, end, handler, type != null ? symbolTable.addConstantClass(type).index : 0, type); if (firstHandler == null) { firstHandler = newHandler; } else { lastHandler.nextHandler = newHandler; } lastHandler = newHandler; }
@Override public void visitProvide(final String service, final String... providers) { provides.putShort(symbolTable.addConstantClass(service).index); provides.putShort(providers.length); for (String provider : providers) { provides.putShort(symbolTable.addConstantClass(provider).index); } providesCount++; }
@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.accessFlags = access; this.thisClass = symbolTable.setMajorVersionAndClassName(version & 0xFFFF, name); if (signature != null) { this.signatureIndex = symbolTable.addConstantUtf8(signature); } this.superClass = superName == null ? 0 : symbolTable.addConstantClass(superName).index; if (interfaces != null && interfaces.length > 0) { interfaceCount = interfaces.length; this.interfaces = new int[interfaceCount]; for (int i = 0; i < interfaceCount; ++i) { this.interfaces[i] = symbolTable.addConstantClass(interfaces[i]).index; } } if (compute == MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL && (version & 0xFFFF) >= Opcodes.V1_7) { compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES; } }
@Override public void visitNestMember(final String nestMember) { if (nestMemberClasses == null) { nestMemberClasses = new ByteVector(); } ++numberOfNestMemberClasses; nestMemberClasses.putShort(symbolTable.addConstantClass(nestMember).index); }
@Override public void visitTypeInsn(final int opcode, final String type) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. Symbol typeSymbol = symbolTable.addConstantClass(type); code.put12(opcode, typeSymbol.index); // If needed, update the maximum stack size and number of locals, and stack map frames. if (currentBasicBlock != null) { if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) { currentBasicBlock.frame.execute(opcode, lastBytecodeOffset, typeSymbol, symbolTable); } else if (opcode == Opcodes.NEW) { // The stack size delta is 1 for NEW, and 0 for ANEWARRAY, CHECKCAST, or INSTANCEOF. int size = relativeStackSize + 1; if (size > maxRelativeStackSize) { maxRelativeStackSize = size; } relativeStackSize = size; } } }
@Override public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. Symbol descSymbol = symbolTable.addConstantClass(descriptor); code.put12(Opcodes.MULTIANEWARRAY, descSymbol.index).putByte(numDimensions); // If needed, update the maximum stack size and number of locals, and stack map frames. if (currentBasicBlock != null) { if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) { currentBasicBlock.frame.execute( Opcodes.MULTIANEWARRAY, numDimensions, descSymbol, symbolTable); } else { // No need to update maxRelativeStackSize (the stack size delta is always negative). relativeStackSize += 1 - numDimensions; } } }
output .putByte(ITEM_OBJECT) .putShort(symbolTable.addConstantClass(symbolTable.getType(typeValue).value).index); break; case UNINITIALIZED_KIND: .putShort(symbolTable.addConstantClass(typeDescriptor.toString()).index);
@Override public final void visitInnerClass( final String name, final String outerName, final String innerName, final int access) { if (innerClasses == null) { innerClasses = new ByteVector(); } // Section 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 info // field of the Symbol of each CONSTANT_Class_info entry C whether an inner class entry has // already been added for C. If so, we store the index of this inner class entry (plus one) in // the info field. This trick allows duplicate detection in O(1) time. Symbol nameSymbol = symbolTable.addConstantClass(name); if (nameSymbol.info == 0) { ++numberOfInnerClasses; innerClasses.putShort(nameSymbol.index); innerClasses.putShort(outerName == null ? 0 : symbolTable.addConstantClass(outerName).index); innerClasses.putShort(innerName == null ? 0 : symbolTable.addConstantUtf8(innerName)); innerClasses.putShort(access); nameSymbol.info = numberOfInnerClasses; } // Else, compare the inner classes entry nameSymbol.info - 1 with the arguments of this method // and throw an exception if there is a difference? }
/** * Adds a CONSTANT_Fieldref_info, CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info to * the constant pool of this symbol table. Does nothing if the constant pool already contains a * similar item. * * @param tag one of {@link Symbol#CONSTANT_FIELDREF_TAG}, {@link Symbol#CONSTANT_METHODREF_TAG} * or {@link Symbol#CONSTANT_INTERFACE_METHODREF_TAG}. * @param owner the internal name of a class. * @param name a field or method name. * @param descriptor a field or method descriptor. * @return a new or already existing Symbol with the given value. */ private Entry addConstantMemberReference( final int tag, final String owner, final String name, final String descriptor) { int hashCode = hash(tag, owner, name, descriptor); Entry entry = get(hashCode); while (entry != null) { if (entry.tag == tag && entry.hashCode == hashCode && entry.owner.equals(owner) && entry.name.equals(name) && entry.value.equals(descriptor)) { return entry; } entry = entry.next; } constantPool.put122( tag, addConstantClass(owner).index, addConstantNameAndType(name, descriptor)); return put(new Entry(constantPoolCount++, tag, owner, name, descriptor, 0, hashCode)); }
/** * Puts the given public API frame element type in {@link #stackMapTableEntries} , using the JVMS * verification_type_info format used in StackMapTable attributes. * * @param type a frame element type described using the same format as in {@link * MethodVisitor#visitFrame}, i.e. either {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link * Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL}, or * {@link Opcodes#UNINITIALIZED_THIS}, or the internal name of a class, or a Label designating * a NEW instruction (for uninitialized types). */ private void putFrameType(final Object type) { if (type instanceof Integer) { stackMapTableEntries.putByte(((Integer) type).intValue()); } else if (type instanceof String) { stackMapTableEntries .putByte(Frame.ITEM_OBJECT) .putShort(symbolTable.addConstantClass((String) type).index); } else { stackMapTableEntries .putByte(Frame.ITEM_UNINITIALIZED) .putShort(((Label) type).bytecodeOffset); } }
this.exceptionIndexTable = new int[numberOfExceptions]; for (int i = 0; i < numberOfExceptions; ++i) { this.exceptionIndexTable[i] = symbolTable.addConstantClass(exceptions[i]).index;
int typeSort = type.getSort(); if (typeSort == Type.OBJECT) { return addConstantClass(type.getInternalName()); } else if (typeSort == Type.METHOD) { return addConstantMethodType(type.getDescriptor()); } else { // type is a primitive or array type. return addConstantClass(type.getDescriptor());