0N/A/*
2362N/A * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A
0N/A/*
0N/A * The Original Code is HAT. The Initial Developer of the
0N/A * Original Code is Bill Foote, with contributions from others
245N/A * at JavaSoft/Sun.
0N/A */
0N/A
0N/Apackage com.sun.tools.hat.internal.model;
0N/A
0N/Aimport java.util.Enumeration;
0N/Aimport java.util.HashMap;
0N/Aimport java.util.Map;
0N/Aimport com.sun.tools.hat.internal.util.Misc;
0N/A
0N/A
0N/A/**
0N/A *
0N/A * @author Bill Foote
0N/A */
0N/A
0N/A/**
0N/A * Represents an object that's allocated out of the Java heap. It occupies
0N/A * memory in the VM, and is the sort of thing that in a JDK 1.1 VM had
0N/A * a handle. It can be a
0N/A * JavaClass, a JavaObjectArray, a JavaValueArray or a JavaObject.
0N/A */
0N/A
0N/Apublic abstract class JavaHeapObject extends JavaThing {
0N/A
0N/A //
0N/A // Who we refer to. This is heavily optimized for space, because it's
0N/A // well worth trading a bit of speed for less swapping.
0N/A // referers and referersLen go through two phases: Building and
0N/A // resolved. When building, referers might have duplicates, but can
0N/A // be appended to. When resolved, referers has no duplicates or
0N/A // empty slots.
0N/A //
0N/A private JavaThing[] referers = null;
0N/A private int referersLen = 0; // -1 when resolved
0N/A
0N/A public abstract JavaClass getClazz();
0N/A public abstract int getSize();
0N/A public abstract long getId();
0N/A
0N/A /**
0N/A * Do any initialization this thing needs after its data is read in.
0N/A * Subclasses that override this should call super.resolve().
0N/A */
0N/A public void resolve(Snapshot snapshot) {
0N/A StackTrace trace = snapshot.getSiteTrace(this);
0N/A if (trace != null) {
0N/A trace.resolve(snapshot);
0N/A }
0N/A }
0N/A
0N/A //
0N/A // Eliminate duplicates from referers, and size the array exactly.
0N/A // This sets us up to answer queries. See the comments around the
0N/A // referers data member for details.
0N/A //
0N/A void setupReferers() {
0N/A if (referersLen > 1) {
0N/A // Copy referers to map, screening out duplicates
0N/A Map<JavaThing, JavaThing> map = new HashMap<JavaThing, JavaThing>();
0N/A for (int i = 0; i < referersLen; i++) {
0N/A if (map.get(referers[i]) == null) {
0N/A map.put(referers[i], referers[i]);
0N/A }
0N/A }
0N/A
0N/A // Now copy into the array
0N/A referers = new JavaThing[map.size()];
0N/A map.keySet().toArray(referers);
0N/A }
0N/A referersLen = -1;
0N/A }
0N/A
0N/A
0N/A /**
0N/A * @return the id of this thing as hex string
0N/A */
0N/A public String getIdString() {
0N/A return Misc.toHex(getId());
0N/A }
0N/A
0N/A public String toString() {
0N/A return getClazz().getName() + "@" + getIdString();
0N/A }
0N/A
0N/A /**
0N/A * @return the StackTrace of the point of allocation of this object,
0N/A * or null if unknown
0N/A */
0N/A public StackTrace getAllocatedFrom() {
0N/A return getClazz().getSiteTrace(this);
0N/A }
0N/A
0N/A public boolean isNew() {
0N/A return getClazz().isNew(this);
0N/A }
0N/A
0N/A void setNew(boolean flag) {
0N/A getClazz().setNew(this, flag);
0N/A }
0N/A
0N/A /**
0N/A * Tell the visitor about all of the objects we refer to
0N/A */
0N/A public void visitReferencedObjects(JavaHeapObjectVisitor v) {
0N/A v.visit(getClazz());
0N/A }
0N/A
0N/A void addReferenceFrom(JavaHeapObject other) {
0N/A if (referersLen == 0) {
0N/A referers = new JavaThing[1]; // It was null
0N/A } else if (referersLen == referers.length) {
0N/A JavaThing[] copy = new JavaThing[(3 * (referersLen + 1)) / 2];
0N/A System.arraycopy(referers, 0, copy, 0, referersLen);
0N/A referers = copy;
0N/A }
0N/A referers[referersLen++] = other;
0N/A // We just append to referers here. Measurements have shown that
0N/A // around 10% to 30% are duplicates, so it's better to just append
0N/A // blindly and screen out all the duplicates at once.
0N/A }
0N/A
0N/A void addReferenceFromRoot(Root r) {
0N/A getClazz().addReferenceFromRoot(r, this);
0N/A }
0N/A
0N/A /**
0N/A * If the rootset includes this object, return a Root describing one
0N/A * of the reasons why.
0N/A */
0N/A public Root getRoot() {
0N/A return getClazz().getRoot(this);
0N/A }
0N/A
0N/A /**
0N/A * Tell who refers to us.
0N/A *
0N/A * @return an Enumeration of JavaHeapObject instances
0N/A */
0N/A public Enumeration getReferers() {
0N/A if (referersLen != -1) {
0N/A throw new RuntimeException("not resolved: " + getIdString());
0N/A }
0N/A return new Enumeration() {
0N/A
0N/A private int num = 0;
0N/A
0N/A public boolean hasMoreElements() {
0N/A return referers != null && num < referers.length;
0N/A }
0N/A
0N/A public Object nextElement() {
0N/A return referers[num++];
0N/A }
0N/A };
0N/A }
0N/A
0N/A /**
0N/A * Given other, which the caller promises is in referers, determines if
0N/A * the reference is only a weak reference.
0N/A */
0N/A public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) {
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * Describe the reference that this thing has to target. This will only
0N/A * be called if target is in the array returned by getChildrenForRootset.
0N/A */
0N/A public String describeReferenceTo(JavaThing target, Snapshot ss) {
0N/A return "??";
0N/A }
0N/A
0N/A public boolean isHeapAllocated() {
0N/A return true;
0N/A }
0N/A
0N/A}