public class ClassFile extends CfEntry implements AttributeHandler
TODO: Explain how to parse byte[] or file or path, how to generate byte[] or file or path.
This class is useful for parsing existing class files from a byte[] image, such as a disk file. It is also used to generate a valid class file image by the builder package, which is a convenient facade for dynamically generating bytecode.
This implementation is efficient internally for both parsing and generation of classfiles, relying on linked lists and internal hashing to maintain performance while minimizing object creation.
The Java classfile is structured as follows (excerpted from the VM Spec):
ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; }
The goal of this particular implementation is to allow direct access/ manipulation of all attributes while providing a convenient facade.
Constructor and Description |
---|
ClassFile(ConstantPool cpool,
java.lang.String className,
java.lang.String superclassName,
java.lang.String sourceFile)
Create a new ClassFile, using the given ConstantPool as a template.
|
ClassFile(java.lang.String className,
java.lang.String superclassName,
java.lang.String sourceFile)
Create a new ClassFile.
|
Modifier and Type | Method and Description |
---|---|
CfField |
addField(int accessFlags,
int nameCp,
int signatureCp)
Add a new field to the class.
|
CfField |
addField(int accessFlags,
java.lang.String name,
java.lang.Class fieldClass)
Add a new field.
|
CfField |
addField(int accessFlags,
java.lang.String name,
CpClass signature)
Add a new object field to the class, having the type of the given
CpClass signature.
|
CfField |
addField(int accessFlags,
java.lang.String name,
java.lang.String signature)
Add a new field to the class.
|
void |
addInterface(java.lang.Class clas)
Append the given interface to the list implemented by this class.
|
void |
addInterface(java.lang.String className)
Append the given interface to the list implemented by this class.
|
CfMethod |
addMethod(int accessFlags,
java.lang.String nameAndSignature)
Add a new method to the class.
|
CfMethod |
addMethod(int accessFlags,
java.lang.String name,
java.lang.String signature)
Add a new method to the class.
|
static ClassFile |
fromArray(byte[] buffer)
Construct a ClassFile from a byte[].
|
static ClassFile |
fromFile(java.lang.String path)
Read a class file from a local file path.
|
CpClass |
getClassCp() |
int |
getClassIndex()
Return the index into the constant pool that holds the name of the class.
|
java.lang.String |
getClassName()
Return the fully qualify VM formatted name of this class, eg the string
as defined in the constant pool which defines the full name of this
class.
|
CodeBuilder |
getCodeBuilder(CfMethod method)
Initialize and return a CodeBuilder for constructing the bytecode
of the given method.
|
ConstantPool |
getConstantPool() |
CfField |
getField(java.lang.String fieldName)
Lookup a field in this classfile by name.
|
int |
getFieldCount() |
CfField |
getFields() |
java.lang.String[] |
getInterfaceNames() |
int[] |
getInterfaces() |
int |
getMajor() |
CfMethod |
getMethod(java.lang.String name,
java.lang.String signature)
Lookup a method by name and signature.
|
int |
getMethodCount() |
CfMethod |
getMethods() |
int |
getMinor() |
java.lang.String |
getPackage()
Return the package portion of the class name in VM format (with "/" instead of ".").
|
java.lang.String |
getSourcefile()
Return the source file from the SourceFile attribute.
|
int |
getSourcefileCp()
Return the sourcefile name index, a CpUtf8 index.
|
CpClass |
getSuperclassCp() |
int |
getSuperclassIndex() |
java.lang.String |
getSuperclassName() |
boolean |
handleAttribute(java.io.DataInputStream dataIn,
java.lang.String name,
int length)
Process an attribute, returning true if we handled it, false otherwise.
|
void |
read(java.io.DataInputStream dataIn)
Read class file fields from stream, overwriting any previous values.
|
void |
releaseCodeBuilder(CodeBuilder builder)
Notify the ClassFile that it can re-use the given CodeBuilder.
|
void |
setClassName(java.lang.String className)
Change the class name.
|
void |
setSourcefile(java.lang.String sourcefile)
Set the source file.
|
void |
setSourcefileCp(int sourcefileCp)
Set the sourcefile name index, a CpUtf8 index.
|
void |
write(java.io.DataOutput dout)
Write this ClassFile to the given stream.
|
void |
write(java.io.OutputStream stream)
Write the ClassFile to the given output stream.
|
void |
write(java.lang.String path)
Write the ClassFile to the given local file path.
|
byte[] |
writeToArray()
Write the class file image to a byte array and return it.
|
getAccessFlags, getAttributeCount, getAttributes, isAbstract, isDeprecated, isFinal, isInterface, isNative, isPrivate, isProtected, isPublic, isStatic, isStrict, isSynchronized, isTransient, isVolatile, setAbstract, setAccessFlags, setAttributes, setDeprecated, setFinal, setInterface, setNative, setPrivate, setProtected, setPublic, setStatic, setStrict, setSynchronized, setTransient, setVolatile
public ClassFile(java.lang.String className, java.lang.String superclassName, java.lang.String sourceFile)
The ConstantPool is created with its default initial capacity.
className
- The name of the class, in VM format (using "/").superclassName
- The name of the superclass, such as "java/lang/Object".sourceFile
- The name of the source file.public ClassFile(ConstantPool cpool, java.lang.String className, java.lang.String superclassName, java.lang.String sourceFile)
cpool
- The constant pool to use as a template.className
- The name of the class, in VM format (using "/").superclassName
- The name of the superclass, such as "java/lang/Object".sourceFile
- The name of the source file.public static ClassFile fromFile(java.lang.String path) throws java.io.IOException, ClassFileFormatException
path
- The path to the classfile.java.io.IOException
ClassFileFormatException
public static ClassFile fromArray(byte[] buffer) throws ClassFileFormatException
ClassFileFormatException
public void read(java.io.DataInputStream dataIn) throws java.io.IOException, ClassFileFormatException
java.io.IOException
ClassFileFormatException
public boolean handleAttribute(java.io.DataInputStream dataIn, java.lang.String name, int length) throws java.io.IOException, ClassFileFormatException
This is called while processing the attribute table as the classfile is read.
handleAttribute
in interface AttributeHandler
dataIn
- DataInputStream, positioned to attribute's data.name
- Attribute name from constant pool.length
- Length of info[] in bytes.java.io.IOException
- If an I/O error ocurrs.ClassFileFormatException
- If the attribute was processed but
was incorrectly formed.public void write(java.io.DataOutput dout) throws java.io.IOException
java.io.IOException
public void write(java.lang.String path) throws java.io.IOException
java.io.IOException
public void write(java.io.OutputStream stream) throws java.io.IOException
The stream will be closed at the end of writing.
java.io.IOException
public byte[] writeToArray()
public int getMinor()
public int getMajor()
public ConstantPool getConstantPool()
public int getClassIndex()
The index must reference a CpClass entry.
public CpClass getClassCp()
public java.lang.String getClassName()
public void setClassName(java.lang.String className)
className
- public int getSuperclassIndex()
public CpClass getSuperclassCp()
public java.lang.String getSuperclassName()
public int[] getInterfaces()
public java.lang.String[] getInterfaceNames()
public void addInterface(java.lang.String className)
className
- Classname in either VM or JLS format (with preceding
'@' of course).public void addInterface(java.lang.Class clas)
clas
- public int getFieldCount()
public CfField getFields()
public int getMethodCount()
public CfMethod getMethods()
public java.lang.String getSourcefile()
public void setSourcefile(java.lang.String sourcefile)
public int getSourcefileCp()
public void setSourcefileCp(int sourcefileCp)
sourcefileCp
- the sourcefile name index, a CpUtf8 index.public java.lang.String getPackage()
public CfMethod addMethod(int accessFlags, java.lang.String nameAndSignature)
accessFlags
- Or'ing of ACC_PUBLIC, ACC_XXX, etc.nameAndSignature
- A short format including the method name AND
the signature in either VM or short format. Both
"getString()Ljava/lang/String;" and "@getString()String" are allowed
here.public CfMethod addMethod(int accessFlags, java.lang.String name, java.lang.String signature)
The signature can be in VM format, or in the friendly format (preceded with an '@').
public CfMethod getMethod(java.lang.String name, java.lang.String signature)
The signature must be in the VM format, such as "(Ljava/lang/String;)V".
name
- The method name.signature
- The method signature in VM format.public CfField addField(int accessFlags, java.lang.String name, java.lang.String signature)
public CfField addField(int accessFlags, java.lang.String name, java.lang.Class fieldClass)
accessFlags
- name
- fieldClass
- The class of the field, including primitive types such
as Integer.TYPE.public CfField addField(int accessFlags, int nameCp, int signatureCp)
public CfField addField(int accessFlags, java.lang.String name, CpClass signature)
public CfField getField(java.lang.String fieldName)
fieldName
- The name of the field.public CodeBuilder getCodeBuilder(CfMethod method)
method
- The method whose Code attribute is to be constructed.public void releaseCodeBuilder(CodeBuilder builder)
If there is an existing CodeBuilder, then the existing one is kept and the one given here is ignored. It only attempts to cache a single instance, since this is all not thread-safe anyway there shouldn't often be two builders active at the same time (although that is permitted, so longs as not accessed by different threads).
Copyright ? 2000-2003 Clarity Systems Group, LLC. All Rights Reserved.