Class ClassFileWriter


  • public class ClassFileWriter
    extends java.lang.Object
    ClassFileWriter A ClassFileWriter is used to write a Java class file. Methods are provided to create fields and methods, and within methods to write Java bytecodes.
    • Field Detail

      • itsSuperBlockStarts

        private int[] itsSuperBlockStarts
      • itsSuperBlockStartsTop

        private int itsSuperBlockStartsTop
      • itsJumpFroms

        private UintMap itsJumpFroms
      • MajorVersion

        private static final int MajorVersion
      • MinorVersion

        private static final int MinorVersion
      • GenerateStackMap

        private static final boolean GenerateStackMap
      • generatedClassName

        private java.lang.String generatedClassName
      • itsExceptionTableTop

        private int itsExceptionTableTop
      • itsLineNumberTable

        private int[] itsLineNumberTable
      • itsLineNumberTableTop

        private int itsLineNumberTableTop
      • itsCodeBuffer

        private byte[] itsCodeBuffer
      • itsCodeBufferTop

        private int itsCodeBufferTop
      • itsStackTop

        private short itsStackTop
      • itsMaxStack

        private short itsMaxStack
      • itsMaxLocals

        private short itsMaxLocals
      • itsMethods

        private ObjArray itsMethods
      • itsInterfaces

        private ObjArray itsInterfaces
      • itsFlags

        private short itsFlags
      • itsThisClassIndex

        private short itsThisClassIndex
      • itsSuperClassIndex

        private short itsSuperClassIndex
      • itsSourceFileNameIndex

        private short itsSourceFileNameIndex
      • itsLabelTable

        private int[] itsLabelTable
      • itsLabelTableTop

        private int itsLabelTableTop
      • itsFixupTable

        private long[] itsFixupTable
      • itsFixupTableTop

        private int itsFixupTableTop
      • itsVarDescriptors

        private ObjArray itsVarDescriptors
      • itsBootstrapMethods

        private ObjArray itsBootstrapMethods
      • itsBootstrapMethodsLength

        private int itsBootstrapMethodsLength
      • tmpCharBuffer

        private char[] tmpCharBuffer
    • Constructor Detail

      • ClassFileWriter

        public ClassFileWriter​(java.lang.String className,
                               java.lang.String superClassName,
                               java.lang.String sourceFileName)
        Construct a ClassFileWriter for a class.
        Parameters:
        className - the name of the class to write, including full package qualification.
        superClassName - the name of the superclass of the class to write, including full package qualification.
        sourceFileName - the name of the source file to use for producing debug information, or null if debug information is not desired
    • Method Detail

      • getClassName

        public final java.lang.String getClassName()
      • addInterface

        public void addInterface​(java.lang.String interfaceName)
        Add an interface implemented by this class. This method may be called multiple times for classes that implement multiple interfaces.
        Parameters:
        interfaceName - a name of an interface implemented by the class being written, including full package qualification.
      • setFlags

        public void setFlags​(short flags)
        Set the class's flags. Flags must be a set of the following flags, bitwise or'd together: ACC_PUBLIC ACC_PRIVATE ACC_PROTECTED ACC_FINAL ACC_ABSTRACT TODO: check that this is the appropriate set
        Parameters:
        flags - the set of class flags to set
      • getSlashedForm

        static java.lang.String getSlashedForm​(java.lang.String name)
      • classNameToSignature

        public static java.lang.String classNameToSignature​(java.lang.String name)
        Convert Java class name in dot notation into "Lname-with-dots-replaced-by-slashes;" form suitable for use as JVM type signatures.
      • addField

        public void addField​(java.lang.String fieldName,
                             java.lang.String type,
                             short flags)
        Add a field to the class.
        Parameters:
        fieldName - the name of the field
        type - the type of the field using ...
        flags - the attributes of the field, such as ACC_PUBLIC, etc. bitwise or'd together
      • addField

        public void addField​(java.lang.String fieldName,
                             java.lang.String type,
                             short flags,
                             int value)
        Add a field to the class.
        Parameters:
        fieldName - the name of the field
        type - the type of the field using ...
        flags - the attributes of the field, such as ACC_PUBLIC, etc. bitwise or'd together
        value - an initial integral value
      • addField

        public void addField​(java.lang.String fieldName,
                             java.lang.String type,
                             short flags,
                             long value)
        Add a field to the class.
        Parameters:
        fieldName - the name of the field
        type - the type of the field using ...
        flags - the attributes of the field, such as ACC_PUBLIC, etc. bitwise or'd together
        value - an initial long value
      • addField

        public void addField​(java.lang.String fieldName,
                             java.lang.String type,
                             short flags,
                             double value)
        Add a field to the class.
        Parameters:
        fieldName - the name of the field
        type - the type of the field using ...
        flags - the attributes of the field, such as ACC_PUBLIC, etc. bitwise or'd together
        value - an initial double value
      • addVariableDescriptor

        public void addVariableDescriptor​(java.lang.String name,
                                          java.lang.String type,
                                          int startPC,
                                          int register)
        Add Information about java variable to use when generating the local variable table.
        Parameters:
        name - variable name.
        type - variable type as bytecode descriptor string.
        startPC - the starting bytecode PC where this variable is live, or -1 if it does not have a Java register.
        register - the Java register number of variable or -1 if it does not have a Java register.
      • startMethod

        public void startMethod​(java.lang.String methodName,
                                java.lang.String type,
                                short flags)
        Add a method and begin adding code. This method must be called before other methods for adding code, exception tables, etc. can be invoked.
        Parameters:
        methodName - the name of the method
        type - a string representing the type
        flags - the attributes of the field, such as ACC_PUBLIC, etc. bitwise or'd together
      • stopMethod

        public void stopMethod​(short maxLocals)
        Complete generation of the method. After this method is called, no more code can be added to the method begun with startMethod.
        Parameters:
        maxLocals - the maximum number of local variable slots (a.k.a. Java registers) used by the method
      • add

        public void add​(int theOpCode)
        Add the single-byte opcode to the current method.
        Parameters:
        theOpCode - the opcode of the bytecode
      • add

        public void add​(int theOpCode,
                        int theOperand)
        Add a single-operand opcode to the current method.
        Parameters:
        theOpCode - the opcode of the bytecode
        theOperand - the operand of the bytecode
      • addLoadConstant

        public void addLoadConstant​(int k)
        Generate the load constant bytecode for the given integer.
        Parameters:
        k - the constant
      • addLoadConstant

        public void addLoadConstant​(long k)
        Generate the load constant bytecode for the given long.
        Parameters:
        k - the constant
      • addLoadConstant

        public void addLoadConstant​(float k)
        Generate the load constant bytecode for the given float.
        Parameters:
        k - the constant
      • addLoadConstant

        public void addLoadConstant​(double k)
        Generate the load constant bytecode for the given double.
        Parameters:
        k - the constant
      • addLoadConstant

        public void addLoadConstant​(java.lang.String k)
        Generate the load constant bytecode for the given string.
        Parameters:
        k - the constant
      • add

        public void add​(int theOpCode,
                        int theOperand1,
                        int theOperand2)
        Add the given two-operand bytecode to the current method.
        Parameters:
        theOpCode - the opcode of the bytecode
        theOperand1 - the first operand of the bytecode
        theOperand2 - the second operand of the bytecode
      • add

        public void add​(int theOpCode,
                        java.lang.String className)
      • add

        public void add​(int theOpCode,
                        java.lang.String className,
                        java.lang.String fieldName,
                        java.lang.String fieldType)
      • addInvoke

        public void addInvoke​(int theOpCode,
                              java.lang.String className,
                              java.lang.String methodName,
                              java.lang.String methodType)
      • addInvokeDynamic

        public void addInvokeDynamic​(java.lang.String methodName,
                                     java.lang.String methodType,
                                     ClassFileWriter.MHandle bsm,
                                     java.lang.Object... bsmArgs)
      • addPush

        public void addPush​(int k)
        Generate code to load the given integer on stack.
        Parameters:
        k - the constant
      • addPush

        public void addPush​(boolean k)
      • addPush

        public void addPush​(long k)
        Generate code to load the given long on stack.
        Parameters:
        k - the constant
      • addPush

        public void addPush​(double k)
        Generate code to load the given double on stack.
        Parameters:
        k - the constant
      • addPush

        public void addPush​(java.lang.String k)
        Generate the code to leave on stack the given string even if the string encoding exeeds the class file limit for single string constant
        Parameters:
        k - the constant
      • isUnderStringSizeLimit

        public boolean isUnderStringSizeLimit​(java.lang.String k)
        Check if k fits limit on string constant size imposed by class file format.
        Parameters:
        k - the string constant
      • addIStore

        public void addIStore​(int local)
        Store integer from stack top into the given local.
        Parameters:
        local - number of local register
      • addLStore

        public void addLStore​(int local)
        Store long from stack top into the given local.
        Parameters:
        local - number of local register
      • addFStore

        public void addFStore​(int local)
        Store float from stack top into the given local.
        Parameters:
        local - number of local register
      • addDStore

        public void addDStore​(int local)
        Store double from stack top into the given local.
        Parameters:
        local - number of local register
      • addAStore

        public void addAStore​(int local)
        Store object from stack top into the given local.
        Parameters:
        local - number of local register
      • addILoad

        public void addILoad​(int local)
        Load integer from the given local into stack.
        Parameters:
        local - number of local register
      • addLLoad

        public void addLLoad​(int local)
        Load long from the given local into stack.
        Parameters:
        local - number of local register
      • addFLoad

        public void addFLoad​(int local)
        Load float from the given local into stack.
        Parameters:
        local - number of local register
      • addDLoad

        public void addDLoad​(int local)
        Load double from the given local into stack.
        Parameters:
        local - number of local register
      • addALoad

        public void addALoad​(int local)
        Load object from the given local into stack.
        Parameters:
        local - number of local register
      • addLoadThis

        public void addLoadThis()
        Load "this" into stack.
      • xop

        private void xop​(int shortOp,
                         int op,
                         int local)
      • addTableSwitch

        public int addTableSwitch​(int low,
                                  int high)
      • markTableSwitchDefault

        public final void markTableSwitchDefault​(int switchStart)
      • markTableSwitchCase

        public final void markTableSwitchCase​(int switchStart,
                                              int caseIndex)
      • markTableSwitchCase

        public final void markTableSwitchCase​(int switchStart,
                                              int caseIndex,
                                              int stackTop)
      • setTableSwitchJump

        public void setTableSwitchJump​(int switchStart,
                                       int caseIndex,
                                       int jumpTarget)
        Set a jump case for a tableswitch instruction. The jump target should be marked as a super block start for stack map generation.
      • acquireLabel

        public int acquireLabel()
      • markLabel

        public void markLabel​(int label)
      • markLabel

        public void markLabel​(int label,
                              short stackTop)
      • markHandler

        public void markHandler​(int theLabel)
      • getLabelPC

        public int getLabelPC​(int label)
      • addLabelFixup

        private void addLabelFixup​(int label,
                                   int fixupSite)
      • fixLabelGotos

        private void fixLabelGotos()
      • getCurrentCodeOffset

        public int getCurrentCodeOffset()
        Get the current offset into the code of the current method.
        Returns:
        an integer representing the offset
      • getStackTop

        public short getStackTop()
      • setStackTop

        public void setStackTop​(short n)
      • adjustStackTop

        public void adjustStackTop​(int delta)
      • addToCodeBuffer

        private void addToCodeBuffer​(int b)
      • addToCodeInt16

        private void addToCodeInt16​(int value)
      • addReservedCodeSpace

        private int addReservedCodeSpace​(int size)
      • addExceptionHandler

        public void addExceptionHandler​(int startLabel,
                                        int endLabel,
                                        int handlerLabel,
                                        java.lang.String catchClassName)
      • addLineNumberEntry

        public void addLineNumberEntry​(short lineNumber)
      • arrayTypeToName

        private static char arrayTypeToName​(int type)
        Convert a newarray operand into an internal type.
      • classDescriptorToInternalName

        private static java.lang.String classDescriptorToInternalName​(java.lang.String descriptor)
        Convert a class descriptor into an internal name. For example, descriptor Ljava/lang/Object; becomes java/lang/Object.
      • descriptorToInternalName

        private static java.lang.String descriptorToInternalName​(java.lang.String descriptor)
        Convert a non-method type descriptor into an internal type.
        Parameters:
        descriptor - the simple type descriptor to convert
      • createInitialLocals

        private int[] createInitialLocals()
        Compute the initial local variable array for the current method. Creates an array of the size of the method's max locals, regardless of the number of parameters in the method.
      • write

        public void write​(java.io.OutputStream oStream)
                   throws java.io.IOException
        Write the class file to the OutputStream.
        Parameters:
        oStream - the stream to write to
        Throws:
        java.io.IOException - if writing to the stream produces an exception
      • getWriteSize

        private int getWriteSize()
      • toByteArray

        public byte[] toByteArray()
        Get the class file as array of bytesto the OutputStream.
      • putInt64

        static int putInt64​(long value,
                            byte[] array,
                            int offset)
      • badStack

        private static void badStack​(int value)
      • sizeOfParameters

        private static int sizeOfParameters​(java.lang.String pString)
      • putInt16

        static int putInt16​(int value,
                            byte[] array,
                            int offset)
      • putInt32

        static int putInt32​(int value,
                            byte[] array,
                            int offset)
      • opcodeLength

        private static int opcodeLength​(int opcode,
                                        boolean wide)
        Size of a bytecode instruction, counting the opcode and its operands. This is different from opcodeCount, since opcodeCount counts logical operands.
      • opcodeCount

        private static int opcodeCount​(int opcode)
        Number of operands accompanying the opcode.
      • stackChange

        private static int stackChange​(int opcode)
        The effect on the operand stack of a given opcode.
      • bytecodeStr

        private static java.lang.String bytecodeStr​(int code)
      • getCharBuffer

        final char[] getCharBuffer​(int minimalSize)
      • addSuperBlockStart

        private void addSuperBlockStart​(int pc)
        Add a pc as the start of super block. A pc is the beginning of a super block if: - pc == 0 - it is the target of a branch instruction - it is the beginning of an exception handler - it is directly after an unconditional jump
      • finalizeSuperBlockStarts

        private void finalizeSuperBlockStarts()
        Sort the list of recorded super block starts and remove duplicates. Also adds exception handling blocks as block starts, since there is no explicit control flow to these. Used for stack map table generation.