503 lines · 14.6 KB · Java
RawDownload
/* * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */  /* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; import java.util.Vector;import java.util.Enumeration;import com.sun.tools.hat.internal.util.CompositeEnumeration;import com.sun.tools.hat.internal.parser.ReadBuffer; /** * * @author      Bill Foote */  public class JavaClass extends JavaHeapObject {    // my id    private long id;    // my name    private String name;     // These are JavaObjectRef before resolve    private JavaThing superclass;    private JavaThing loader;    private JavaThing signers;    private JavaThing protectionDomain;     // non-static fields    private JavaField[] fields;    // static fields    private JavaStatic[] statics;     private static final JavaClass[] EMPTY_CLASS_ARRAY = new JavaClass[0];    // my subclasses    private JavaClass[] subclasses = EMPTY_CLASS_ARRAY;     // my instances    private Vector<JavaHeapObject> instances = new Vector<JavaHeapObject>();     // Who I belong to.  Set on resolve.    private Snapshot mySnapshot;     // Size of an instance, including VM overhead    private int instanceSize;    // Total number of fields including inherited ones    private int totalNumFields;      public JavaClass(long id, String name, long superclassId, long loaderId,                     long signersId, long protDomainId,                     JavaField[] fields, JavaStatic[] statics,                     int instanceSize) {        this.id = id;        this.name = name;        this.superclass = new JavaObjectRef(superclassId);        this.loader = new JavaObjectRef(loaderId);        this.signers = new JavaObjectRef(signersId);        this.protectionDomain = new JavaObjectRef(protDomainId);        this.fields = fields;        this.statics = statics;        this.instanceSize = instanceSize;    }     public JavaClass(String name, long superclassId, long loaderId,                     long signersId, long protDomainId,                     JavaField[] fields, JavaStatic[] statics,                     int instanceSize) {        this(-1L, name, superclassId, loaderId, signersId,             protDomainId, fields, statics, instanceSize);    }     public final JavaClass getClazz() {        return mySnapshot.getJavaLangClass();    }     public final int getIdentifierSize() {        return mySnapshot.getIdentifierSize();    }     public final int getMinimumObjectSize() {        return mySnapshot.getMinimumObjectSize();    }     public void resolve(Snapshot snapshot) {        if (mySnapshot != null) {            return;        }        mySnapshot = snapshot;        resolveSuperclass(snapshot);        if (superclass != null) {            ((JavaClass) superclass).addSubclass(this);        }         loader  = loader.dereference(snapshot, null);        signers  = signers.dereference(snapshot, null);        protectionDomain  = protectionDomain.dereference(snapshot, null);         for (int i = 0; i < statics.length; i++) {            statics[i].resolve(this, snapshot);        }        snapshot.getJavaLangClass().addInstance(this);        super.resolve(snapshot);        return;    }     /**     * Resolve our superclass.  This might be called well before     * all instances are available (like when reading deferred     * instances in a 1.2 dump file :-)  Calling this is sufficient     * to be able to explore this class' fields.     */    public void resolveSuperclass(Snapshot snapshot) {        if (superclass == null) {            // We must be java.lang.Object, so we have no superclass.        } else {            totalNumFields = fields.length;            superclass = superclass.dereference(snapshot, null);            if (superclass == snapshot.getNullThing()) {                superclass = null;            } else {                try {                    JavaClass sc = (JavaClass) superclass;                    sc.resolveSuperclass(snapshot);                    totalNumFields += sc.totalNumFields;                } catch (ClassCastException ex) {                    System.out.println("Warning!  Superclass of " + name + " is " + superclass);                    superclass = null;                }            }        }    }     public boolean isString() {        return mySnapshot.getJavaLangString() == this;    }     public boolean isClassLoader() {        return mySnapshot.getJavaLangClassLoader().isAssignableFrom(this);    }     /**     * Get a numbered field from this class     */    public JavaField getField(int i) {        if (i < 0 || i >= fields.length) {            throw new Error("No field " + i + " for " + name);        }        return fields[i];    }     /**     * Get the total number of fields that are part of an instance of     * this class.  That is, include superclasses.     */    public int getNumFieldsForInstance() {        return totalNumFields;    }     /**     * Get a numbered field from all the fields that are part of instance     * of this class.  That is, include superclasses.     */    public JavaField getFieldForInstance(int i) {        if (superclass != null) {            JavaClass sc = (JavaClass) superclass;            if (i < sc.totalNumFields) {                return sc.getFieldForInstance(i);            }            i -= sc.totalNumFields;        }        return getField(i);    }     /**     * Get the class responsible for field i, where i is a field number that     * could be passed into getFieldForInstance.     *     * @see JavaClass.getFieldForInstance()     */    public JavaClass getClassForField(int i) {        if (superclass != null) {            JavaClass sc = (JavaClass) superclass;            if (i < sc.totalNumFields) {                return sc.getClassForField(i);            }        }        return this;    }     public long getId() {        return id;    }     public String getName() {        return name;    }     public boolean isArray() {        return name.indexOf('[') != -1;    }     public Enumeration getInstances(boolean includeSubclasses) {        if (includeSubclasses) {            Enumeration res = instances.elements();            for (int i = 0; i < subclasses.length; i++) {                res = new CompositeEnumeration(res,                              subclasses[i].getInstances(true));            }            return res;        } else {            return instances.elements();        }    }     /**     * @return a count of the instances of this class     */    public int getInstancesCount(boolean includeSubclasses) {        int result = instances.size();        if (includeSubclasses) {            for (int i = 0; i < subclasses.length; i++) {                result += subclasses[i].getInstancesCount(includeSubclasses);            }        }        return result;    }     public JavaClass[] getSubclasses() {        return subclasses;    }     /**     * This can only safely be called after resolve()     */    public JavaClass getSuperclass() {        return (JavaClass) superclass;    }     /**     * This can only safely be called after resolve()     */    public JavaThing getLoader() {        return loader;    }     /**     * This can only safely be called after resolve()     */    public boolean isBootstrap() {        return loader == mySnapshot.getNullThing();    }     /**     * This can only safely be called after resolve()     */    public JavaThing getSigners() {        return signers;    }     /**     * This can only safely be called after resolve()     */    public JavaThing getProtectionDomain() {        return protectionDomain;    }     public JavaField[] getFields() {        return fields;    }     /**     * Includes superclass fields     */    public JavaField[] getFieldsForInstance() {        Vector<JavaField> v = new Vector<JavaField>();        addFields(v);        JavaField[] result = new JavaField[v.size()];        for (int i = 0; i < v.size(); i++) {            result[i] =  v.elementAt(i);        }        return result;    }      public JavaStatic[] getStatics() {        return statics;    }     // returns value of static field of given name    public JavaThing getStaticField(String name) {        for (int i = 0; i < statics.length; i++) {            JavaStatic s = statics[i];            if (s.getField().getName().equals(name)) {                return s.getValue();            }        }        return null;    }     public String toString() {        return "class " + name;    }     public int compareTo(JavaThing other) {        if (other instanceof JavaClass) {            return name.compareTo(((JavaClass) other).name);        }        return super.compareTo(other);    }      /**     * @return true iff a variable of type this is assignable from an instance     *          of other     */    public boolean isAssignableFrom(JavaClass other) {        if (this == other) {            return true;        } else if (other == null) {            return false;        } else {            return isAssignableFrom((JavaClass) other.superclass);            // Trivial tail recursion:  I have faith in javac.        }    }     /**     * Describe the reference that this thing has to target.  This will only     * be called if target is in the array returned by getChildrenForRootset.     */     public String describeReferenceTo(JavaThing target, Snapshot ss) {        for (int i = 0; i < statics.length; i++) {            JavaField f = statics[i].getField();            if (f.hasId()) {                JavaThing other = statics[i].getValue();                if (other == target) {                    return "static field " + f.getName();                }            }        }        return super.describeReferenceTo(target, ss);    }     /**     * @return the size of an instance of this class.  Gives 0 for an array     *          type.     */    public int getInstanceSize() {        return instanceSize + mySnapshot.getMinimumObjectSize();    }      /**     * @return The size of all instances of this class.  Correctly handles     *          arrays.     */    public long getTotalInstanceSize() {        int count = instances.size();        if (count == 0 || !isArray()) {            return count * instanceSize;        }         // array class and non-zero count, we have to        // get the size of each instance and sum it        long result = 0;        for (int i = 0; i < count; i++) {            JavaThing t = (JavaThing) instances.elementAt(i);            result += t.getSize();        }        return result;    }     /**     * @return the size of this object     */    public int getSize() {        JavaClass cl = mySnapshot.getJavaLangClass();        if (cl == null) {            return 0;        } else {            return cl.getInstanceSize();        }    }     public void visitReferencedObjects(JavaHeapObjectVisitor v) {        super.visitReferencedObjects(v);        JavaHeapObject sc = getSuperclass();        if (sc != null) v.visit(getSuperclass());         JavaThing other;        other = getLoader();        if (other instanceof JavaHeapObject) {            v.visit((JavaHeapObject)other);        }        other = getSigners();        if (other instanceof JavaHeapObject) {            v.visit((JavaHeapObject)other);        }        other = getProtectionDomain();        if (other instanceof JavaHeapObject) {            v.visit((JavaHeapObject)other);        }         for (int i = 0; i < statics.length; i++) {            JavaField f = statics[i].getField();            if (!v.exclude(this, f) && f.hasId()) {                other = statics[i].getValue();                if (other instanceof JavaHeapObject) {                    v.visit((JavaHeapObject) other);                }            }        }    }     // package-privates below this point    final ReadBuffer getReadBuffer() {        return mySnapshot.getReadBuffer();    }     final void setNew(JavaHeapObject obj, boolean flag) {        mySnapshot.setNew(obj, flag);    }     final boolean isNew(JavaHeapObject obj) {        return mySnapshot.isNew(obj);    }     final StackTrace getSiteTrace(JavaHeapObject obj) {        return mySnapshot.getSiteTrace(obj);    }     final void addReferenceFromRoot(Root root, JavaHeapObject obj) {        mySnapshot.addReferenceFromRoot(root, obj);    }     final Root getRoot(JavaHeapObject obj) {        return mySnapshot.getRoot(obj);    }     final Snapshot getSnapshot() {        return mySnapshot;    }     void addInstance(JavaHeapObject inst) {        instances.addElement(inst);    }     // Internals only below this point    private void addFields(Vector<JavaField> v) {        if (superclass != null) {            ((JavaClass) superclass).addFields(v);        }        for (int i = 0; i < fields.length; i++) {            v.addElement(fields[i]);        }    }     private void addSubclassInstances(Vector<JavaHeapObject> v) {        for (int i = 0; i < subclasses.length; i++) {            subclasses[i].addSubclassInstances(v);        }        for (int i = 0; i < instances.size(); i++) {            v.addElement(instances.elementAt(i));        }    }     private void addSubclass(JavaClass sub) {        JavaClass newValue[] = new JavaClass[subclasses.length + 1];        System.arraycopy(subclasses, 0, newValue, 0, subclasses.length);        newValue[subclasses.length] = sub;

Lines 1–500 of 503.