com.claritysys.jvm.classfile
Class ClassFile

java.lang.Object
  extended by com.claritysys.jvm.classfile.CfEntry
      extended by com.claritysys.jvm.classfile.ClassFile
All Implemented Interfaces:
AttributeHandler

public class ClassFile
extends CfEntry
implements AttributeHandler

ClassFile represents a Java class file (as stored on disk), as per the Java Virtual Machine Specification, 2nd Edition, and exposes the attributes of a classfile in convenient Java data formats (e.g., int as opposed to U2).

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.

Classfile Format

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 Summary
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.
 
Method Summary
 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.
 
Methods inherited from class com.claritysys.jvm.classfile.CfEntry
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
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

ClassFile

public ClassFile(java.lang.String className,
                 java.lang.String superclassName,
                 java.lang.String sourceFile)
Create a new ClassFile.

The ConstantPool is created with its default initial capacity.

Parameters:
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.

ClassFile

public 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.

Parameters:
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.
Method Detail

fromFile

public static ClassFile fromFile(java.lang.String path)
                          throws java.io.IOException,
                                 ClassFileFormatException
Read a class file from a local file path.

Parameters:
path - The path to the classfile.
Returns:
a ClassFile
Throws:
java.io.IOException
ClassFileFormatException

fromArray

public static ClassFile fromArray(byte[] buffer)
                           throws ClassFileFormatException
Construct a ClassFile from a byte[].

Throws:
ClassFileFormatException

read

public void read(java.io.DataInputStream dataIn)
          throws java.io.IOException,
                 ClassFileFormatException
Read class file fields from stream, overwriting any previous values.

Throws:
java.io.IOException
ClassFileFormatException

handleAttribute

public boolean handleAttribute(java.io.DataInputStream dataIn,
                               java.lang.String name,
                               int length)
                        throws java.io.IOException,
                               ClassFileFormatException
Process an attribute, returning true if we handled it, false otherwise.

This is called while processing the attribute table as the classfile is read.

Specified by:
handleAttribute in interface AttributeHandler
Parameters:
dataIn - DataInputStream, positioned to attribute's data.
name - Attribute name from constant pool.
length - Length of info[] in bytes.
Returns:
true if the handler processed it, false if not.
Throws:
java.io.IOException - If an I/O error ocurrs.
ClassFileFormatException - If the attribute was processed but was incorrectly formed.

write

public void write(java.io.DataOutput dout)
           throws java.io.IOException
Write this ClassFile to the given stream.

Throws:
java.io.IOException

write

public void write(java.lang.String path)
           throws java.io.IOException
Write the ClassFile to the given local file path.

Throws:
java.io.IOException

write

public void write(java.io.OutputStream stream)
           throws java.io.IOException
Write the ClassFile to the given output stream.

The stream will be closed at the end of writing.

Throws:
java.io.IOException

writeToArray

public byte[] writeToArray()
Write the class file image to a byte array and return it.

Returns:
The classfile as a byte[] in memory.

getMinor

public int getMinor()

getMajor

public int getMajor()

getConstantPool

public ConstantPool getConstantPool()

getClassIndex

public int getClassIndex()
Return the index into the constant pool that holds the name of the class.

The index must reference a CpClass entry.

Returns:

getClassCp

public CpClass getClassCp()

getClassName

public 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.

Returns:
The name of the class, in VM format, from the constant pool.

setClassName

public void setClassName(java.lang.String className)
Change the class name. This does not remove the old classname from the constant pool.

Parameters:
className -

getSuperclassIndex

public int getSuperclassIndex()

getSuperclassCp

public CpClass getSuperclassCp()

getSuperclassName

public java.lang.String getSuperclassName()

getInterfaces

public int[] getInterfaces()

getInterfaceNames

public java.lang.String[] getInterfaceNames()

addInterface

public void addInterface(java.lang.String className)
Append the given interface to the list implemented by this class.

Parameters:
className - Classname in either VM or JLS format (with preceding '@' of course).

addInterface

public void addInterface(java.lang.Class clas)
Append the given interface to the list implemented by this class.

Parameters:
clas -

getFieldCount

public int getFieldCount()

getFields

public CfField getFields()

getMethodCount

public int getMethodCount()

getMethods

public CfMethod getMethods()

getSourcefile

public java.lang.String getSourcefile()
Return the source file from the SourceFile attribute.


setSourcefile

public void setSourcefile(java.lang.String sourcefile)
Set the source file.


getSourcefileCp

public int getSourcefileCp()
Return the sourcefile name index, a CpUtf8 index.

Returns:
the sourcefile name index, a CpUtf8 index.

setSourcefileCp

public void setSourcefileCp(int sourcefileCp)
Set the sourcefile name index, a CpUtf8 index.

Parameters:
sourcefileCp - the sourcefile name index, a CpUtf8 index.

getPackage

public java.lang.String getPackage()
Return the package portion of the class name in VM format (with "/" instead of ".").

Returns:
The package portion of the class name, minus the trailing slash. Returns null if the class is not in a package.

addMethod

public CfMethod addMethod(int accessFlags,
                          java.lang.String nameAndSignature)
Add a new method to the class.

Parameters:
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.

addMethod

public CfMethod addMethod(int accessFlags,
                          java.lang.String name,
                          java.lang.String signature)
Add a new method to the class.

The signature can be in VM format, or in the friendly format (preceded with an '@').


getMethod

public CfMethod getMethod(java.lang.String name,
                          java.lang.String signature)
Lookup a method by name and signature.

The signature must be in the VM format, such as "(Ljava/lang/String;)V".

Parameters:
name - The method name.
signature - The method signature in VM format.
Returns:
The method or null if none found with that name/signature.

addField

public CfField addField(int accessFlags,
                        java.lang.String name,
                        java.lang.String signature)
Add a new field to the class.


addField

public CfField addField(int accessFlags,
                        java.lang.String name,
                        java.lang.Class fieldClass)
Add a new field.

Parameters:
accessFlags -
name -
fieldClass - The class of the field, including primitive types such as Integer.TYPE.
Returns:

addField

public CfField addField(int accessFlags,
                        int nameCp,
                        int signatureCp)
Add a new field to the class.


addField

public 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.


getField

public CfField getField(java.lang.String fieldName)
Lookup a field in this classfile by name.

Parameters:
fieldName - The name of the field.
Returns:
The CfField or null if not found.

getCodeBuilder

public CodeBuilder getCodeBuilder(CfMethod method)
Initialize and return a CodeBuilder for constructing the bytecode of the given method.

Parameters:
method - The method whose Code attribute is to be constructed.
Returns:
An initialized CodeBuilder.

releaseCodeBuilder

public void releaseCodeBuilder(CodeBuilder builder)
Notify the ClassFile that it can re-use the given CodeBuilder. This is called by the CodeBuilder during its flush() method to signify that it can be re-used for another method.

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.