Jode 1.90-CVS
Build Aug 6, 2004

net.sf.jode.bytecode
Class ClassInfo

java.lang.Object
  extended bynet.sf.jode.bytecode.BinaryInfo
      extended bynet.sf.jode.bytecode.ClassInfo
All Implemented Interfaces:
java.lang.Comparable

public final class ClassInfo
extends BinaryInfo
implements java.lang.Comparable

Represents a class or interface. It can't be used for primitive or array types. Every class/interface is associated with a class path, which is used to load the class and its dependent classes.

ClassInfo and ClassPath

Every ClassInfo instance belongs to a ClassPath. This class path is used to find the class and its dependent classes, e.g. the super class. Even if you want to create a class info from the scratch you have to associate it with a class path, in which the dependent classes are searched. For every class path and every class name there exists at most one class info object with this class name. The only exception is when you overwrite a loaded class, e.g. by calling setName().

Creating a Class

As you can see, there is no public constructor. Instead you create a new ClassInfo, by calling ClassPath.getClassInfo(java.lang.String). Multiple calls of this method with the same class name result in the same object. The resulting ClassInfo is initially empty and you now have three different means to fill it with informations: You can load the class from its classpath (from which it was created), you can guess the information (useful if the class can't be loaded), or you build it from scratch by setting its contents with the various setSomething methods.

Changing a Class

Whether or not the classinfo was already filled with information, you can change it. You can, for example, provide another array of methods, change the modifiers, or rename the class. Use the various setSomething methods.

The Components of a Class

A class consists of several components:
name
The name of the class. The name is already set, when you create a new ClassInfo with getClassInfo. If you change this name this has some consequences, read the description of the setName(java.lang.String) method.
class name
The short java name of this class, i.e. the name that appears behind the "class" keyword in the java source file. While getClassName() also works for package scope classes, setClassName() must only be called on inner classes and will not change the bytecode name.
E.g.: The ClassName of java.util.Map$Entry is Entry. If you change its ClassName to Yrtne and save it, it will still be in a file called Map$Entry.class, but a debugger would call it java.util.Map.Yrtne. Note that you should also save Map, because it also has a reference to the ClassName.
modifiers
There is a set of access modifiers (AKA access flags) attached to each class. They are represented as integers (bitboard) and can be conveniently accessed via Modifier.
Inner classes can have more modifiers than normal classes, as they can be private, protected or static. These extended modifiers are supported, too.
TODO: Check that reflection returns the extended modifiers!
superclass
Every class except java.lang.Object has a super class. The super class is created in the same classpath as the current class. Interfaces always have java.lang.Object as their super class.
interfaces
Every class (resp. interfaces) can implement (resp. extend) zero or more interfaces.
signature
The classes super class and interfaces with template information.
fields
Fields are represented as FieldInfo objects.
methods
Methods are represented as MethodInfo objects.
method scoped
A boolean value; true if this class is an anonymous or method scoped class.
outer class
the class in which this class or interface was declared. It returns null for package scoped and method scoped classes.
classes
the inner classes declared in this class. This doesn't include method scoped classes.
source file
The name of source file. The JVM uses this field when a stack trace is produced. It may be null if the class was compiled without debugging information.

Inner Classes

Inner classes are supported as far as the information is present in the bytecode. However, you can always ignore this inner information, and access inner classes by their bytecode name, e.g. java.util.Map$Entry. There are four different types of classes:
normal package scoped classes
A class is package scoped if, and only if getOuterClass() returns null and isMethodScoped() returns false.
class scoped classes (inner classes)
A class is class scoped if, and only if getOuterClass() returns not null. The bytecode name (getName()) of an inner class is in normally of the form Package.Outer$Inner. However, ClassInfo also supports differently named classes, as long as the InnerClass attribute is present. The method getClassName() returns the name of the inner class (Inner in the above example). You can get all inner classes of a class with the method getClasses().
named method scoped classes
A class is a named method scoped class if, and only if isMethodScoped() returns true and getClassName() returns not null. In that case getOuterClass() returns null, too.

The bytecode name (getName()) of a method scoped class is normally of the form Package.Outer$Number$Inner. However, ClassInfo also supports differently named classes, as long as the InnerClass attribute is present.

There's no way to get the method scoped classes of a method, except by analyzing its instructions. And even that is error prone, since it could just be a method scoped class of an outer method.
anonymous classes
A class is an anonymous class if, and only if isMethodScoped() returns true and getClassName() returns null. In that case getOuterClass() returns null, too.

The bytecode name (getName()) of a method scoped class is normally of the form Package.Outer$Number. However, ClassInfo also supports differently named classes, as long as the InnerClass attribute is present.

There's no way to get the anonymous classes of a method, except by analyzing its instructions. And even that is error prone, since it could just be an anonymous class of an outer method.

Open Question

I represent most types as String objects (type signatures); this is convenient since java bytecode does the same. On the other hand a class type should be represented as ClassInfo object. There is a method in TypeSignature to convert between them, which needs a class path. This is a bit difficult to use.
However the alternative would be to represents types as ClassInfo and create ClassInfo objects for primitive and array types. But this contradicts the purpose of this class, which is to read and write class files. I think the current solution is okay.

Author:
Jochen Hoenicke

Field Summary
static int ALL
          This constant can be used as parameter to load.
static int ALMOSTALL
          This constant can be used as parameter to load.
static int DECLARATIONS
          This constant can be used as parameter to load.
static int HIERARCHY
          This constant can be used as parameter to load.
static int NODEBUG
          This constant can be used as parameter to load.
static int NONE
          This constant can be used as parameter to drop.
static int OUTERCLASS
          This constant can be used as parameter to load.
static int PUBLICDECLARATIONS
          This constant can be used as parameter to load.
 
Fields inherited from class net.sf.jode.bytecode.BinaryInfo
ACC_ABSTRACT, ACC_ANNOTATION, ACC_BRIDGE, ACC_ENUM, ACC_FINAL, ACC_INTERFACE, ACC_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNTHETIC, ACC_TRANSIENT, ACC_VARARGS, ACC_VOLATILE
 
Method Summary
 int compareTo(java.lang.Object other)
          Compares two ClassInfo objects for name order.
 void drop(int keep)
          This is the counter part to load and guess.
static boolean exists(java.lang.String name)
          Deprecated.  
 FieldInfo findField(java.lang.String name, java.lang.String typeSig)
          Searches for a field with given name and type signature.
 MethodInfo findMethod(java.lang.String name, java.lang.String typeSig)
          Searches for a method with given name and type signature.
static ClassInfo forName(java.lang.String name)
          Deprecated.  
protected  int getAttributeCount()
          Count the attributes needed by the class.
 ClassInfo[] getClasses()
          Gets the inner classes declared in this class.
static java.util.Enumeration getClassesAndPackages(java.lang.String packageName)
          Deprecated.  
 java.lang.String getClassName()
          Returns the java class name of a class, without package or outer classes.
 ClassPath getClassPath()
          Returns the classpath in which this class was created.
 FieldInfo[] getFields()
          Gets the fields (class and member variables) of this class.
 ClassInfo[] getInterfaces()
          Returns the ClassInfo object for the super class.
 MethodInfo[] getMethods()
          Gets the methods of this class.
 int getModifiers()
          Gets the modifiers of this class, e.g. public or abstract.
 java.lang.String getName()
          Returns the full qualified name of this class.
 ClassInfo getOuterClass()
          Returns the outer class of this class if it is an inner class.
 long getSerialVersionUID()
          Gets the serial version UID of this class.
 java.lang.String getSignature()
          Gets the type signature including template information of the class.
 java.lang.String getSourceFile()
           
 ClassInfo getSuperclass()
          Returns the ClassInfo object for the super class.
 void guess(int howMuch)
          Guess the contents of a class.
 boolean implementedBy(ClassInfo clazz)
          Checks if this interface is implemented by clazz.
 boolean isDeprecated()
          Checks whether this class was declared as deprecated.
 boolean isGuessed()
          Tells whether the information in this class was guessed by a call to guess(int).
 boolean isInterface()
          Checks whether this class info represents an interface.
 boolean isMethodScoped()
          Tells whether the class was declared inside a method.
static boolean isPackage(java.lang.String name)
          Deprecated.  
 void load(int howMuch)
          Loads the contents of a class from its class path.
 void read(java.io.DataInputStream input, int howMuch)
          Reads a class file from a data input stream.
protected  void readAttribute(java.lang.String name, int length, ConstantPool cp, java.io.DataInputStream input, int howMuch)
          Reads in an attributes of this class.
 void setClasses(ClassInfo[] ic)
           
static void setClassPath(ClassPath path)
          Deprecated.  
static void setClassPath(java.lang.String path)
          Deprecated.  
 void setDeprecated(boolean flag)
           
 void setFields(FieldInfo[] fi)
           
 void setInterfaces(ClassInfo[] newIfaces)
           
 void setMethods(MethodInfo[] mi)
           
 void setMethodScoped(boolean ms)
           
 void setModifiers(int newModifiers)
           
 void setName(java.lang.String newName)
          Sets the name of this class info.
 void setOuterClass(ClassInfo oc)
           
 void setSourceFile(java.lang.String newSource)
           
 void setSuperclass(ClassInfo newSuper)
           
 boolean superClassOf(ClassInfo child)
          Checks if this class is a super class of child.
 java.lang.String toString()
          Returns a string representation of the class.
 void write(java.io.DataOutputStream out)
          Writes a class to the given DataOutputStream.
protected  void writeAttributes(GrowableConstantPool gcp, java.io.DataOutputStream output)
          Write the attributes needed by the class, namely SourceFile and InnerClasses attributes.
 
Methods inherited from class net.sf.jode.bytecode.BinaryInfo
addAttribute, findAttribute, getAttributes, getAttributeSize, prepareAttributes, removeAllAttributes, removeAttribute
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

NONE

public static final int NONE
This constant can be used as parameter to drop. It specifies that no information at all should be kept for the current class.

See Also:
load(int), Constant Field Values

OUTERCLASS

public static final int OUTERCLASS
This constant can be used as parameter to load. It specifies that at least the outer class information should be loaded, i.e. the outer class and the java class name. It is the only information that is loaded recursively: It is also automatically loaded for all classes that are accessed by this class. The reason for the recursive load is simple: In java bytecode a class contains the outer class information for all classes that it accesses, so we can create this information without the need to read the outer class. We also need this information when writing a class.

See Also:
load(int), Constant Field Values

HIERARCHY

public static final int HIERARCHY
This constant can be used as parameter to load. It specifies that at least the hierarchy information, i.e. the superclass/interfaces fields and the modifiers of this class should be loaded.

See Also:
load(int), Constant Field Values

PUBLICDECLARATIONS

public static final int PUBLICDECLARATIONS
This constant can be used as parameter to load. It specifies that all public fields, methods and inner class declarations should be loaded. It doesn't load method bodies.

See Also:
load(int), Constant Field Values

DECLARATIONS

public static final int DECLARATIONS
This constant can be used as parameter to load. It specifies that all the fields, methods and inner class declaration should be loaded. It doesn't load method bodies.

See Also:
load(int), Constant Field Values

NODEBUG

public static final int NODEBUG
This constant can be used as parameter to load. It specifies that everything in the class except debugging information and non-standard attributes should be loaded.

See Also:
load(int), Constant Field Values

ALMOSTALL

public static final int ALMOSTALL
This constant can be used as parameter to load. It specifies that everything in the class except non-standard attributes should be loaded.

See Also:
load(int), Constant Field Values

ALL

public static final int ALL
This constant can be used as parameter to load. It specifies that everything in the class should be loaded.

See Also:
load(int), Constant Field Values
Method Detail

setClassPath

public static void setClassPath(java.lang.String path)
Deprecated.  


setClassPath

public static void setClassPath(ClassPath path)
Deprecated.  


exists

public static boolean exists(java.lang.String name)
Deprecated.  


isPackage

public static boolean isPackage(java.lang.String name)
Deprecated.  


getClassesAndPackages

public static java.util.Enumeration getClassesAndPackages(java.lang.String packageName)
Deprecated.  


forName

public static ClassInfo forName(java.lang.String name)
Deprecated.  


getClassPath

public ClassPath getClassPath()
Returns the classpath in which this class was created.


readAttribute

protected void readAttribute(java.lang.String name,
                             int length,
                             ConstantPool cp,
                             java.io.DataInputStream input,
                             int howMuch)
                      throws java.io.IOException
Description copied from class: BinaryInfo
Reads in an attributes of this class. Overwrite this method if you want to handle your own attributes. If you don't know how to handle an attribute call this method for the super class.

Overrides:
readAttribute in class BinaryInfo
Parameters:
name - the attribute name.
length - the length of the attribute.
cp - the constant pool of the class.
input - a data input stream where you can read the attribute from. It will protect you to read more over the attribute boundary.
howMuch - the constant that was given to the load(int) function when loading this class.
Throws:
java.io.IOException

read

public void read(java.io.DataInputStream input,
                 int howMuch)
          throws java.io.IOException
Reads a class file from a data input stream. Normally you should load a class from its classpath instead. This may be useful for special kinds of input streams, that ClassPath doesn't handle.

Parameters:
input - The input stream, containing the class in standard bytecode format.
howMuch - The amount of information that should be read in, one of HIERARCHY, PUBLICDECLARATIONS, DECLARATIONS or ALL.
Throws:
ClassFormatException - if the file doesn't denote a valid class.
java.io.IOException - if input throws an exception.
java.lang.IllegalStateException - if this ClassInfo was modified.
See Also:
load(int)

getAttributeCount

protected int getAttributeCount()
Count the attributes needed by the class.

Overrides:
getAttributeCount in class BinaryInfo
Returns:
the number of attributes of this class.

writeAttributes

protected void writeAttributes(GrowableConstantPool gcp,
                               java.io.DataOutputStream output)
                        throws java.io.IOException
Write the attributes needed by the class, namely SourceFile and InnerClasses attributes.

Overrides:
writeAttributes in class BinaryInfo
Parameters:
gcp - The growable constant pool, which is not growable anymore (see above).
output - the data output stream. You must write exactly as many bytes to it as you have told with the BinaryInfo.getAttributeSize() method.
Throws:
java.io.IOException

write

public void write(java.io.DataOutputStream out)
           throws java.io.IOException
Writes a class to the given DataOutputStream. Of course this only works if ALL information for this class is loaded/set. If this class has an outer class, inner classes or extra classes, their status must contain at least the OUTERCLASS information.

Parameters:
out - the output stream.
Throws:
java.io.IOException - if out throws io exception.
java.lang.IllegalStateException - if not enough information is set.

load

public void load(int howMuch)
          throws java.io.IOException
Loads the contents of a class from its class path.

Parameters:
howMuch - The amount of information that should be loaded at least, one of OUTERCLASS, HIERARCHY, PUBLICDECLARATIONS, DECLARATIONS, NODEBUG, ALMOSTALL or ALL. Note that more information than requested can be loaded if this is convenient.
Throws:
ClassFormatException - if the file doesn't denote a valid class.
java.io.FileNotFoundException - if class wasn't found in classpath.
java.io.IOException - if an io exception occured while reading the class.
java.lang.SecurityException - if a security manager prohibits loading the class.
java.lang.IllegalStateException - if this ClassInfo was modified by calling one of the setSomething methods.

guess

public void guess(int howMuch)
Guess the contents of a class. This is a last resort if the file can't be read by the class path. It generates outer class information based on the class name, assumes that the class extends java.lang.Object, implements no interfaces and has no fields, methods or inner classes.

Parameters:
howMuch - The amount of information that should be read, e.g. HIERARCHY.
See Also:
OUTERCLASS, HIERARCHY, PUBLICDECLARATIONS, DECLARATIONS, ALMOSTALL, ALL

drop

public void drop(int keep)
This is the counter part to load and guess. It will drop all informations bigger than "keep" and clean up the memory. Note that drop should be used with care if more than one thread accesses this ClassInfo.

Overrides:
drop in class BinaryInfo
Parameters:
keep - tells how much info we should keep, can be NONE or anything that load accepts.
See Also:
load(int)

getName

public java.lang.String getName()
Returns the full qualified name of this class.

Returns:
the full qualified name of this class, an interned string.

isGuessed

public boolean isGuessed()
Tells whether the information in this class was guessed by a call to guess(int).

Returns:
true if the information was guessed.

getClassName

public java.lang.String getClassName()
Returns the java class name of a class, without package or outer classes. This is null for an anonymous class. For other classes it is the name that occured after the class keyword (provided it was compiled from java). This need OUTERCLASS information loaded to work properly.

Returns:
the short name of this class. Returns null for anonymous classes.
Throws:
java.lang.IllegalStateException - if OUTERCLASS information wasn't loaded yet.

getSuperclass

public ClassInfo getSuperclass()
Returns the ClassInfo object for the super class.

Returns:
the short name of this class.
Throws:
java.lang.IllegalStateException - if HIERARCHY information wasn't loaded yet.

getInterfaces

public ClassInfo[] getInterfaces()
Returns the ClassInfo object for the super class.

Returns:
the short name of this class.
Throws:
java.lang.IllegalStateException - if HIERARCHY information wasn't loaded yet.

getSignature

public java.lang.String getSignature()
Gets the type signature including template information of the class. WARNING: This field may disappear and merged into getType later.

Returns:
the type signature.
See Also:
TypeSignature

getModifiers

public int getModifiers()
Gets the modifiers of this class, e.g. public or abstract. The information is only available if at least HIERARCHY is loaded.

Returns:
a bitboard of the modifiers.
See Also:
Class.getModifiers(), ACC_* fields in BinaryInfo

isInterface

public boolean isInterface()
Checks whether this class info represents an interface. The information is only available if at least HIERARCHY is loaded.

Returns:
true if this class info represents an interface.

isDeprecated

public boolean isDeprecated()
Checks whether this class was declared as deprecated. In bytecode this is represented by a special attribute.

Returns:
true if this class info represents a deprecated class.

findField

public FieldInfo findField(java.lang.String name,
                           java.lang.String typeSig)
Searches for a field with given name and type signature.

Parameters:
name - the name of the field.
typeSig - the type signature of the field.
Returns:
the field info for the field.

findMethod

public MethodInfo findMethod(java.lang.String name,
                             java.lang.String typeSig)
Searches for a method with given name and type signature.

Parameters:
name - the name of the method.
typeSig - the type signature of the method.
Returns:
the method info for the method.

getMethods

public MethodInfo[] getMethods()
Gets the methods of this class.


getFields

public FieldInfo[] getFields()
Gets the fields (class and member variables) of this class.


getOuterClass

public ClassInfo getOuterClass()
Returns the outer class of this class if it is an inner class. This needs the OUTERCLASS information loaded.

Returns:
The class that declared this class, null if the class isn't declared in a class scope
Throws:
java.lang.IllegalStateException - if OUTERCLASS information wasn't loaded yet.

isMethodScoped

public boolean isMethodScoped()
Tells whether the class was declared inside a method. This needs the OUTERCLASS information loaded.

Returns:
true if this is a method scoped or an anonymous class, false otherwise.
Throws:
java.lang.IllegalStateException - if OUTERCLASS information wasn't loaded yet.

getClasses

public ClassInfo[] getClasses()
Gets the inner classes declared in this class. This needs at least PUBLICDECLARATION information loaded.

Returns:
an array containing the inner classes, guaranteed != null.
Throws:
java.lang.IllegalStateException - if PUBLICDECLARATIONS information wasn't loaded yet.

getSourceFile

public java.lang.String getSourceFile()

setName

public void setName(java.lang.String newName)
Sets the name of this class info. Note that by changing the name you may overwrite an already loaded class. This can have ugly effects, as references to that overwritten class may still exist.


setSuperclass

public void setSuperclass(ClassInfo newSuper)

setInterfaces

public void setInterfaces(ClassInfo[] newIfaces)

setModifiers

public void setModifiers(int newModifiers)

setDeprecated

public void setDeprecated(boolean flag)

setMethods

public void setMethods(MethodInfo[] mi)

setFields

public void setFields(FieldInfo[] fi)

setOuterClass

public void setOuterClass(ClassInfo oc)

setMethodScoped

public void setMethodScoped(boolean ms)

setClasses

public void setClasses(ClassInfo[] ic)

setSourceFile

public void setSourceFile(java.lang.String newSource)

getSerialVersionUID

public long getSerialVersionUID()
                         throws java.security.NoSuchAlgorithmException
Gets the serial version UID of this class. If a final static long serialVersionUID field is present, its constant value is returned. Otherwise the UID is calculated with the algorithm in the serial version spec.

Returns:
the serial version UID of this class.
Throws:
java.lang.IllegalStateException - if DECLARATIONS aren't loaded.
java.security.NoSuchAlgorithmException - if SHA-1 message digest is not supported (needed for calculation of UID.

compareTo

public int compareTo(java.lang.Object other)
Compares two ClassInfo objects for name order.

Specified by:
compareTo in interface java.lang.Comparable
Returns:
a positive number if this name lexicographically follows than other's name, a negative number if it preceeds the other, 0 if they are equal.
Throws:
java.lang.ClassCastException - if other is not a ClassInfo.

superClassOf

public boolean superClassOf(ClassInfo child)
                     throws java.io.IOException
Checks if this class is a super class of child. This loads the complete hierarchy of child on demand and can throw an IOException if some classes are not found or broken. It doesn't check for cycles in class hierarchy, so it may get into an eternal loop.

Parameters:
child - the class that should be a child class of us.
Returns:
true if this is as super class of child, false otherwise
Throws:
java.io.IOException - if hierarchy of child could not be loaded.

implementedBy

public boolean implementedBy(ClassInfo clazz)
                      throws java.io.IOException
Checks if this interface is implemented by clazz. This loads the complete hierarchy of clazz on demand and can throw an IOException if some classes are not found or broken. If this class is not an interface it returns false, but you should check it yourself for better performance.
It doesn't check for cycles in class hierarchy, so it may get into an eternal loop.

Parameters:
clazz - the class to be checked.
Returns:
true if this is a interface and is implemented by clazz, false otherwise
Throws:
java.io.IOException - if hierarchy of clazz could not be loaded.

toString

public java.lang.String toString()
Returns a string representation of the class. This is just the full qualified class name.


Jode 1.90-CVS
Build Aug 6, 2004

Copyright © 1998-2004 by Jochen Hoenicke.