FileDocCategorySizeDatePackage
ClassClass.javaAPI DocJ2ME CLDC 1.110712Wed Feb 05 15:56:04 GMT 2003vm

ClassClass.java

/*
 *    ClassClass.java    1.37    99/05/11 SMI
 *
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package vm;
/*
 * VM-specific internal representation of
 * a class. Target-machine independent.
 * There is a references from each instance of components.ClassInfo to 
 * one of these, and a reference back as well.
 *
 * See also JDKVM for VM-specific info not associated directly with a class.
 */
import components.*;
import util.*;
import vm.Const;
import jcc.Str2ID;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;
import java.util.StringTokenizer;

public class
ClassClass {
    public ClassInfo        ci;
    public InterfaceMethodTable    inf;
    public boolean        impureConstants = false;
    public int            nGCStatics = 0;
    public boolean        hasStaticInitializer = false;

    public MethodInfo findFinalizer( ){
    if ( ci == null ) return null;
    if ( ci.methods == null ) return null;
    int n = ci.methods.length;
    for ( int i = 0; i < n ; i++ ){
        if ((ci.methods[i].access & Const.ACC_PRIVATE) != 0 &&
            (ci.methods[i].access & Const.ACC_NATIVE) !=0 &&
            ci.methods[i].name.string.equals(/*NOI18N*/"finalize") &&
            ci.methods[i].type.string.equals(/*NOI18N*/"()V")) {
            return ci.methods[i];
        }
    }
    return null;
    }

    public static void setTypes(){
    classFactory.setTypes();
    }

    /*
     * Make the class list into a vector
     * ordered s.t. superclasses precede their
     * subclasses.
     */
    private static ClassClass[]cvector;
    private static int         cindex;
    private static VMClassFactory classFactory;

    // this is the recursive part
    private static void insertClassElement( ClassInfo e ){
    if ( e.vmClass != null ) return; // already in place.
    ClassInfo sup = e.superClassInfo;
    // make sure our super precedes us.
    if ( (sup != null) && (sup.vmClass == null) ) insertClassElement( sup );
    ClassClass newVmClass = classFactory.newVMClass( e );
    cvector[ cindex++ ] = newVmClass;
    //
    // If the superclass of class C has a <clinit> method, C must
    // be marked as having a static initializer too.
    //
    if (!newVmClass.hasStaticInitializer &&
        (sup != null) && sup.vmClass.hasStaticInitializer) {
        newVmClass.hasStaticInitializer = true;
    }
    }

    // this is the entry point for vector building.
    public static ClassClass[] getClassVector( VMClassFactory ftry ){
    if ( cvector != null ) return cvector; // just once, at most.
    classFactory = ftry;
    cvector = new ClassClass[ ClassInfo.nClasses() ];
    cindex  = 0;
    Enumeration classlist = ClassInfo.allClasses();
    while( classlist.hasMoreElements() ){
        ClassInfo e =  (ClassInfo)classlist.nextElement();
        if (e.vmClass == null) insertClassElement( e );
    }
    return cvector;
    }

    public static void appendClassElement( ClassInfo c ){
    // foo. Have a cvector in place, must now 
    // add a new entry at the end. "c" is it.
    if ( cvector == null ) return; // ...never mind
    ClassClass[] oldCvector = cvector;
    cvector = new ClassClass[ cindex+1 ];
    System.arraycopy( oldCvector, 0, cvector,0, cindex );
    cvector[ cindex ] = classFactory.newVMClass( c );
    }

    /**
     * Size of an instance in WORDS.
     */
    public int instanceSize(){
    FieldConstant rft[] = ci.refFieldtable;
    if ( rft == null || rft.length == 0 ) return 0;
    FieldInfo lastField = rft[rft.length-1].find();
    return (lastField.instanceOffset+lastField.nSlots);
    }

    public boolean isInterface() {
    return (ci.access&Const.ACC_INTERFACE) != 0;
    }

    public boolean hasMethodtable(){
    return ((!isInterface()) && (ci.refMethodtable != null));
    }

    public boolean isArrayClass(){
    return (ci instanceof ArrayClassInfo);
    }

    public boolean isPrimitiveClass() { 
    return (ci instanceof PrimitiveClassInfo);
    }

    public int nmethods(){
    return (ci.methods==null) ? 0 : ci.methods.length;
    }

    public int nfields(){
    return (ci.fields==null)  ? 0 : ci.fields.length;
    }

    /**
     * In the current definition of module (.mclass) files,
     * many sorts of constants are put in the shared constant
     * pool, and never in the per-class constant pool. This includes
     * Unicode constants and NameAndType constants. This is fine
     * as long as all symbols in the per-class constant pools get
     * resolved, as they won't be missed. However, if we wish to
     * process classes with symbol references that are not fully 
     * resolved, we will have to add such elements into the constant
     * pool. We do this by sweeping over the per-class constants,
     * looking for method, field, and class references that are not
     * resolved, and adding the necessary entries.
     */
    public void
    adjustSymbolicConstants(){
    ConstantObject consts[] = ci.constants;
    if (!isPartiallyResolved(consts)) {
        return;
    }
    //
    // we have work to do. This is unfortunate.
    // we use a LocalConstantPool to manage the pool we're re-building.
    // Because order matters, we collect the new entries to add at end.
    //
    System.err.println(Localizer.getString("classclass.warning_class_has_an_impure_constant_pool", ci.className));
    ci.constants = makeResolvable(consts).getConstants(); 
    impureConstants = true;
    }

    public static boolean 
    isPartiallyResolved( ConstantObject[] consts ){
        if ( consts == null ) return false; // no const!
        int nconst = consts.length;
        if ( nconst == 0 ) return false; // no const!

        // first see if we have anything that needs our attention.
        int nsymbolic = 0;
        for( int i = 1; i < nconst; i += consts[i].nSlots ){
            ConstantObject o = consts[i];
            if (!o.isResolved()) {
                return true;
        }
        }
    return false;
    }

    static public ConstantPool 
    makeResolvable(ConstantPool cp) {
    //
        // we use a LocalConstantPool to manage the pool we're re-building.
        // Because order matters, we collect the new entries to add at end.
        //
        System.err.println(Localizer.getString("classclass.warning_it_has_an_impure_shared_constant_pool"));
    return makeResolvable(cp.getConstants());
    }

    static private ConstantPool makeResolvable(ConstantObject[] consts) { 

        LocalConstantPool newPool    = new LocalConstantPool();
        Vector            newEntries = new Vector();
        int               nconst = consts.length;
        for( int i = 1; i < nconst; i += consts[i].nSlots ){
            ConstantObject o;
            o = consts[i];
            newPool.append(o);
            if ( ! o.isResolved() )
                newEntries.addElement( o );
        }
        Enumeration newlist = newEntries.elements();
        while( newlist.hasMoreElements() ){
            ConstantObject o = (ConstantObject)newlist.nextElement();
            switch( o.tag ){
            case Const.CONSTANT_CLASS:
                ClassConstant co = (ClassConstant)o;
                System.err.println(Localizer.getString("classclass.class", co.name.string));
                co.name = (UnicodeConstant)newPool.add( co.name );
                continue;
            case Const.CONSTANT_FIELD:
            case Const.CONSTANT_METHOD:
            case Const.CONSTANT_INTERFACEMETHOD:
                FMIrefConstant fo = (FMIrefConstant)o;
                if ( fo.clas.isResolved() ){
                    // This is a missing member of a resolved class.
                    // Print this out
                    // To print all the references to a totally missing
                    // class would be redundant and noisy.
                    if ( fo.tag == Const.CONSTANT_FIELD ){
                        System.err.print(Localizer.getString("classclass.field"));
                    } else {
                        System.err.print(Localizer.getString("classclass.method"));
                    }
                    System.err.println(Localizer.getString(
                    "classclass.of_class", 
                    fo.sig.name.string, 
                    fo.sig.type.string, 
                    fo.clas.name.string));
                }
                // as NameAndTypeConstant entries are always "resolved",
                // the strings they nominally point to need not be present:
                // they will get written out as a hash ID.
                fo.sig = (NameAndTypeConstant)newPool.add( fo.sig );
                fo.clas.name = (UnicodeConstant)newPool.add( fo.clas.name );
                fo.clas = (ClassConstant)newPool.add( fo.clas );
                continue;
            }
        }
    newPool.impureConstants = true;
    return newPool;
    }

}

/*
 * Like a constant pool, but with simpler semantics.
 * Perhaps this and components.ConstantPool should be related.
 * The important difference is in "add", which never shares
 * and which always clones if it must insert!
 * Also append, which is even simpler, as it assumes that we're
 * loading up this constant pool from an already-existing list.
 */
final
class LocalConstantPool extends components.ConstantPool {

    public LocalConstantPool(){
    super();
    }
    /**
     * Return the ConstantObject in constant table corresponding to
     * the given ConstantObject s.
     * Duplicates and inserts s if it is not already there.
     * The index member of the returned value (which
     * will not be the object s!) will be set to its index in our
     * table. There will be no element of index 0.
     */
    public ConstantObject
    add( ConstantObject s ){
    ConstantObject r = (ConstantObject)h.get( s );
    if ( r == null ){
        r = (ConstantObject)s.clone();
        r.index = n;
        n += r.nSlots;
        h.put( r, r );
        t.addElement( r );
        for ( int i =r.nSlots; i > 1; i-- )
        t.addElement( null ); // place holder.
    }
    r.references+=1;
    return r;
    }

    public void
    append( ConstantObject s ){
    if ( h.get( s ) != null ){
        throw new Error(Localizer.getString(
                "classclass.append.error_already_in_pool",
                 s));
    }
    if ( s.index != n ){
        throw new Error(Localizer.getString(
                "classclass.append.error_out_of_order",
                 s));
    }
    h.put( s, s);
    t.addElement( s );
    s.references+=1;
    for ( int i =s.nSlots; i > 1; i-- )
        t.addElement( null ); // place holder.
    n += s.nSlots;
    }
}