001: /*
002: * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: /*
027: * The contents of this file are subject to the Sun Public License
028: * Version 1.0 (the "License"); you may not use this file except in
029: * compliance with the License. A copy of the License is available at
030: * http://www.sun.com/, and in the file LICENSE.html in the
031: * doc directory.
032: *
033: * The Original Code is HAT. The Initial Developer of the
034: * Original Code is Bill Foote, with contributions from others
035: * at JavaSoft/Sun. Portions created by Bill Foote and others
036: * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved.
037: *
038: * In addition to the formal license, I ask that you don't
039: * change the history or donations files without permission.
040: *
041: */
042:
043: package com.sun.tools.hat.internal.model;
044:
045: import java.util.Enumeration;
046: import java.util.HashMap;
047: import java.util.Map;
048: import com.sun.tools.hat.internal.util.Misc;
049:
050: /**
051: *
052: * @version 1.2, 10/08/98 [jhat @(#)JavaHeapObject.java 1.15 07/05/05]
053: * @author Bill Foote
054: */
055:
056: /**
057: * Represents an object that's allocated out of the Java heap. It occupies
058: * memory in the VM, and is the sort of thing that in a JDK 1.1 VM had
059: * a handle. It can be a
060: * JavaClass, a JavaObjectArray, a JavaValueArray or a JavaObject.
061: */
062:
063: public abstract class JavaHeapObject extends JavaThing {
064:
065: //
066: // Who we refer to. This is heavily optimized for space, because it's
067: // well worth trading a bit of speed for less swapping.
068: // referers and referersLen go through two phases: Building and
069: // resolved. When building, referers might have duplicates, but can
070: // be appended to. When resolved, referers has no duplicates or
071: // empty slots.
072: //
073: private JavaThing[] referers = null;
074: private int referersLen = 0; // -1 when resolved
075:
076: public abstract JavaClass getClazz();
077:
078: public abstract int getSize();
079:
080: public abstract long getId();
081:
082: /**
083: * Do any initialization this thing needs after its data is read in.
084: * Subclasses that override this should call super.resolve().
085: */
086: public void resolve(Snapshot snapshot) {
087: StackTrace trace = snapshot.getSiteTrace(this );
088: if (trace != null) {
089: trace.resolve(snapshot);
090: }
091: }
092:
093: //
094: // Eliminate duplicates from referers, and size the array exactly.
095: // This sets us up to answer queries. See the comments around the
096: // referers data member for details.
097: //
098: void setupReferers() {
099: if (referersLen > 1) {
100: // Copy referers to map, screening out duplicates
101: Map<JavaThing, JavaThing> map = new HashMap<JavaThing, JavaThing>();
102: for (int i = 0; i < referersLen; i++) {
103: if (map.get(referers[i]) == null) {
104: map.put(referers[i], referers[i]);
105: }
106: }
107:
108: // Now copy into the array
109: referers = new JavaThing[map.size()];
110: map.keySet().toArray(referers);
111: }
112: referersLen = -1;
113: }
114:
115: /**
116: * @return the id of this thing as hex string
117: */
118: public String getIdString() {
119: return Misc.toHex(getId());
120: }
121:
122: public String toString() {
123: return getClazz().getName() + "@" + getIdString();
124: }
125:
126: /**
127: * @return the StackTrace of the point of allocation of this object,
128: * or null if unknown
129: */
130: public StackTrace getAllocatedFrom() {
131: return getClazz().getSiteTrace(this );
132: }
133:
134: public boolean isNew() {
135: return getClazz().isNew(this );
136: }
137:
138: void setNew(boolean flag) {
139: getClazz().setNew(this , flag);
140: }
141:
142: /**
143: * Tell the visitor about all of the objects we refer to
144: */
145: public void visitReferencedObjects(JavaHeapObjectVisitor v) {
146: v.visit(getClazz());
147: }
148:
149: void addReferenceFrom(JavaHeapObject other) {
150: if (referersLen == 0) {
151: referers = new JavaThing[1]; // It was null
152: } else if (referersLen == referers.length) {
153: JavaThing[] copy = new JavaThing[(3 * (referersLen + 1)) / 2];
154: System.arraycopy(referers, 0, copy, 0, referersLen);
155: referers = copy;
156: }
157: referers[referersLen++] = other;
158: // We just append to referers here. Measurements have shown that
159: // around 10% to 30% are duplicates, so it's better to just append
160: // blindly and screen out all the duplicates at once.
161: }
162:
163: void addReferenceFromRoot(Root r) {
164: getClazz().addReferenceFromRoot(r, this );
165: }
166:
167: /**
168: * If the rootset includes this object, return a Root describing one
169: * of the reasons why.
170: */
171: public Root getRoot() {
172: return getClazz().getRoot(this );
173: }
174:
175: /**
176: * Tell who refers to us.
177: *
178: * @return an Enumeration of JavaHeapObject instances
179: */
180: public Enumeration getReferers() {
181: if (referersLen != -1) {
182: throw new RuntimeException("not resolved: " + getIdString());
183: }
184: return new Enumeration() {
185:
186: private int num = 0;
187:
188: public boolean hasMoreElements() {
189: return referers != null && num < referers.length;
190: }
191:
192: public Object nextElement() {
193: return referers[num++];
194: }
195: };
196: }
197:
198: /**
199: * Given other, which the caller promises is in referers, determines if
200: * the reference is only a weak reference.
201: */
202: public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) {
203: return false;
204: }
205:
206: /**
207: * Describe the reference that this thing has to target. This will only
208: * be called if target is in the array returned by getChildrenForRootset.
209: */
210: public String describeReferenceTo(JavaThing target, Snapshot ss) {
211: return "??";
212: }
213:
214: public boolean isHeapAllocated() {
215: return true;
216: }
217:
218: }
|