Class ClassFileWriter
- java.lang.Object
-
- org.mozilla.classfile.ClassFileWriter
-
public class ClassFileWriter extends java.lang.Object
ClassFileWriterA ClassFileWriter is used to write a Java class file. Methods are provided to create fields and methods, and within methods to write Java bytecodes.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) class
ClassFileWriter.BootstrapEntry
static class
ClassFileWriter.ClassFileFormatException
Thrown for cases where the error in generating the class file is due to a program size constraints rather than a likely bug in the compiler.static class
ClassFileWriter.MHandle
(package private) class
ClassFileWriter.StackMapTable
A stack map table is a code attribute introduced in Java 6 that gives type information at key points in the method body (namely, at the beginning of each super block after the first).
-
Field Summary
-
Constructor Summary
Constructors Constructor Description ClassFileWriter(java.lang.String className, java.lang.String superClassName, java.lang.String sourceFileName)
Construct a ClassFileWriter for a class.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description int
acquireLabel()
void
add(int theOpCode)
Add the single-byte opcode to the current method.void
add(int theOpCode, int theOperand)
Add a single-operand opcode to the current method.void
add(int theOpCode, int theOperand1, int theOperand2)
Add the given two-operand bytecode to the current method.void
add(int theOpCode, java.lang.String className)
void
add(int theOpCode, java.lang.String className, java.lang.String fieldName, java.lang.String fieldType)
void
addALoad(int local)
Load object from the given local into stack.void
addAStore(int local)
Store object from stack top into the given local.void
addDLoad(int local)
Load double from the given local into stack.void
addDStore(int local)
Store double from stack top into the given local.void
addExceptionHandler(int startLabel, int endLabel, int handlerLabel, java.lang.String catchClassName)
void
addField(java.lang.String fieldName, java.lang.String type, short flags)
Add a field to the class.void
addField(java.lang.String fieldName, java.lang.String type, short flags, double value)
Add a field to the class.void
addField(java.lang.String fieldName, java.lang.String type, short flags, int value)
Add a field to the class.void
addField(java.lang.String fieldName, java.lang.String type, short flags, long value)
Add a field to the class.void
addFLoad(int local)
Load float from the given local into stack.void
addFStore(int local)
Store float from stack top into the given local.void
addILoad(int local)
Load integer from the given local into stack.void
addInterface(java.lang.String interfaceName)
Add an interface implemented by this class.void
addInvoke(int theOpCode, java.lang.String className, java.lang.String methodName, java.lang.String methodType)
void
addInvokeDynamic(java.lang.String methodName, java.lang.String methodType, ClassFileWriter.MHandle bsm, java.lang.Object... bsmArgs)
void
addIStore(int local)
Store integer from stack top into the given local.private void
addLabelFixup(int label, int fixupSite)
void
addLineNumberEntry(short lineNumber)
void
addLLoad(int local)
Load long from the given local into stack.void
addLoadConstant(double k)
Generate the load constant bytecode for the given double.void
addLoadConstant(float k)
Generate the load constant bytecode for the given float.void
addLoadConstant(int k)
Generate the load constant bytecode for the given integer.void
addLoadConstant(long k)
Generate the load constant bytecode for the given long.void
addLoadConstant(java.lang.String k)
Generate the load constant bytecode for the given string.void
addLoadThis()
Load "this" into stack.void
addLStore(int local)
Store long from stack top into the given local.void
addPush(boolean k)
void
addPush(double k)
Generate code to load the given double on stack.void
addPush(int k)
Generate code to load the given integer on stack.void
addPush(long k)
Generate code to load the given long on stack.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 constantprivate int
addReservedCodeSpace(int size)
private void
addSuperBlockStart(int pc)
Add a pc as the start of super block.int
addTableSwitch(int low, int high)
private void
addToCodeBuffer(int b)
private void
addToCodeInt16(int value)
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.void
adjustStackTop(int delta)
private static char
arrayTypeToName(int type)
Convert a newarray operand into an internal type.private static void
badStack(int value)
private static java.lang.String
bytecodeStr(int code)
private static java.lang.String
classDescriptorToInternalName(java.lang.String descriptor)
Convert a class descriptor into an internal name.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.private int[]
createInitialLocals()
Compute the initial local variable array for the current method.private static java.lang.String
descriptorToInternalName(java.lang.String descriptor)
Convert a non-method type descriptor into an internal type.private void
finalizeSuperBlockStarts()
Sort the list of recorded super block starts and remove duplicates.private void
fixLabelGotos()
(package private) char[]
getCharBuffer(int minimalSize)
java.lang.String
getClassName()
int
getCurrentCodeOffset()
Get the current offset into the code of the current method.int
getLabelPC(int label)
(package private) static java.lang.String
getSlashedForm(java.lang.String name)
short
getStackTop()
private int
getWriteSize()
boolean
isUnderStringSizeLimit(java.lang.String k)
Check if k fits limit on string constant size imposed by class file format.void
markHandler(int theLabel)
void
markLabel(int label)
void
markLabel(int label, short stackTop)
void
markTableSwitchCase(int switchStart, int caseIndex)
void
markTableSwitchCase(int switchStart, int caseIndex, int stackTop)
void
markTableSwitchDefault(int switchStart)
private static int
opcodeCount(int opcode)
Number of operands accompanying the opcode.private static int
opcodeLength(int opcode, boolean wide)
Size of a bytecode instruction, counting the opcode and its operands.(package private) static int
putInt16(int value, byte[] array, int offset)
(package private) static int
putInt32(int value, byte[] array, int offset)
(package private) static int
putInt64(long value, byte[] array, int offset)
void
setFlags(short flags)
Set the class's flags.void
setStackTop(short n)
void
setTableSwitchJump(int switchStart, int caseIndex, int jumpTarget)
Set a jump case for a tableswitch instruction.private static int
sizeOfParameters(java.lang.String pString)
private static int
stackChange(int opcode)
The effect on the operand stack of a given opcode.void
startMethod(java.lang.String methodName, java.lang.String type, short flags)
Add a method and begin adding code.void
stopMethod(short maxLocals)
Complete generation of the method.byte[]
toByteArray()
Get the class file as array of bytesto the OutputStream.void
write(java.io.OutputStream oStream)
Write the class file to the OutputStream.private void
xop(int shortOp, int op, int local)
-
-
-
Field Detail
-
ACC_PUBLIC
public static final short ACC_PUBLIC
- See Also:
- Constant Field Values
-
ACC_PRIVATE
public static final short ACC_PRIVATE
- See Also:
- Constant Field Values
-
ACC_PROTECTED
public static final short ACC_PROTECTED
- See Also:
- Constant Field Values
-
ACC_STATIC
public static final short ACC_STATIC
- See Also:
- Constant Field Values
-
ACC_FINAL
public static final short ACC_FINAL
- See Also:
- Constant Field Values
-
ACC_SUPER
public static final short ACC_SUPER
- See Also:
- Constant Field Values
-
ACC_SYNCHRONIZED
public static final short ACC_SYNCHRONIZED
- See Also:
- Constant Field Values
-
ACC_VOLATILE
public static final short ACC_VOLATILE
- See Also:
- Constant Field Values
-
ACC_TRANSIENT
public static final short ACC_TRANSIENT
- See Also:
- Constant Field Values
-
ACC_NATIVE
public static final short ACC_NATIVE
- See Also:
- Constant Field Values
-
ACC_ABSTRACT
public static final short ACC_ABSTRACT
- See Also:
- Constant Field Values
-
itsSuperBlockStarts
private int[] itsSuperBlockStarts
-
itsSuperBlockStartsTop
private int itsSuperBlockStartsTop
-
SuperBlockStartsSize
private static final int SuperBlockStartsSize
- See Also:
- Constant Field Values
-
itsJumpFroms
private UintMap itsJumpFroms
-
LineNumberTableSize
private static final int LineNumberTableSize
- See Also:
- Constant Field Values
-
ExceptionTableSize
private static final int ExceptionTableSize
- See Also:
- Constant Field Values
-
MajorVersion
private static final int MajorVersion
-
MinorVersion
private static final int MinorVersion
-
GenerateStackMap
private static final boolean GenerateStackMap
-
FileHeaderConstant
private static final int FileHeaderConstant
- See Also:
- Constant Field Values
-
DEBUGSTACK
private static final boolean DEBUGSTACK
- See Also:
- Constant Field Values
-
DEBUGLABELS
private static final boolean DEBUGLABELS
- See Also:
- Constant Field Values
-
DEBUGCODE
private static final boolean DEBUGCODE
- See Also:
- Constant Field Values
-
generatedClassName
private java.lang.String generatedClassName
-
itsExceptionTable
private ExceptionTableEntry[] itsExceptionTable
-
itsExceptionTableTop
private int itsExceptionTableTop
-
itsLineNumberTable
private int[] itsLineNumberTable
-
itsLineNumberTableTop
private int itsLineNumberTableTop
-
itsCodeBuffer
private byte[] itsCodeBuffer
-
itsCodeBufferTop
private int itsCodeBufferTop
-
itsConstantPool
private ConstantPool itsConstantPool
-
itsCurrentMethod
private ClassFileMethod itsCurrentMethod
-
itsStackTop
private short itsStackTop
-
itsMaxStack
private short itsMaxStack
-
itsMaxLocals
private short itsMaxLocals
-
itsMethods
private ObjArray itsMethods
-
itsFields
private ObjArray itsFields
-
itsInterfaces
private ObjArray itsInterfaces
-
itsFlags
private short itsFlags
-
itsThisClassIndex
private short itsThisClassIndex
-
itsSuperClassIndex
private short itsSuperClassIndex
-
itsSourceFileNameIndex
private short itsSourceFileNameIndex
-
MIN_LABEL_TABLE_SIZE
private static final int MIN_LABEL_TABLE_SIZE
- See Also:
- Constant Field Values
-
itsLabelTable
private int[] itsLabelTable
-
itsLabelTableTop
private int itsLabelTableTop
-
MIN_FIXUP_TABLE_SIZE
private static final int MIN_FIXUP_TABLE_SIZE
- See Also:
- Constant Field Values
-
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 fieldtype
- 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 fieldtype
- the type of the field using ...flags
- the attributes of the field, such as ACC_PUBLIC, etc. bitwise or'd togethervalue
- 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 fieldtype
- the type of the field using ...flags
- the attributes of the field, such as ACC_PUBLIC, etc. bitwise or'd togethervalue
- 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 fieldtype
- the type of the field using ...flags
- the attributes of the field, such as ACC_PUBLIC, etc. bitwise or'd togethervalue
- 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 methodtype
- a string representing the typeflags
- 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 bytecodetheOperand
- 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 bytecodetheOperand1
- the first operand of the bytecodetheOperand2
- 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.
-
-