1/* 2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27/* 28 * The Original Code is HAT. The Initial Developer of the 29 * Original Code is Bill Foote, with contributions from others 30 * at JavaSoft/Sun. 31 */ 32 33package jdk.test.lib.hprof.model; 34 35import java.util.Enumeration; 36import java.util.HashMap; 37import java.util.Map; 38import jdk.test.lib.hprof.util.Misc; 39 40 41/** 42 * 43 * @author Bill Foote 44 */ 45 46/** 47 * Represents an object that's allocated out of the Java heap. It occupies 48 * memory in the VM, and is the sort of thing that in a JDK 1.1 VM had 49 * a handle. It can be a 50 * JavaClass, a JavaObjectArray, a JavaValueArray or a JavaObject. 51 */ 52 53public abstract class JavaHeapObject extends JavaThing { 54 55 // 56 // Who we refer to. This is heavily optimized for space, because it's 57 // well worth trading a bit of speed for less swapping. 58 // referers and referersLen go through two phases: Building and 59 // resolved. When building, referers might have duplicates, but can 60 // be appended to. When resolved, referers has no duplicates or 61 // empty slots. 62 // 63 private JavaThing[] referers = null; 64 private int referersLen = 0; // -1 when resolved 65 66 public abstract JavaClass getClazz(); 67 public abstract int getSize(); 68 public abstract long getId(); 69 70 /** 71 * Do any initialization this thing needs after its data is read in. 72 * Subclasses that override this should call super.resolve(). 73 */ 74 public void resolve(Snapshot snapshot) { 75 StackTrace trace = snapshot.getSiteTrace(this); 76 if (trace != null) { 77 trace.resolve(snapshot); 78 } 79 } 80 81 // 82 // Eliminate duplicates from referers, and size the array exactly. 83 // This sets us up to answer queries. See the comments around the 84 // referers data member for details. 85 // 86 void setupReferers() { 87 if (referersLen > 1) { 88 // Copy referers to map, screening out duplicates 89 Map<JavaThing, JavaThing> map = new HashMap<JavaThing, JavaThing>(); 90 for (int i = 0; i < referersLen; i++) { 91 if (map.get(referers[i]) == null) { 92 map.put(referers[i], referers[i]); 93 } 94 } 95 96 // Now copy into the array 97 referers = new JavaThing[map.size()]; 98 map.keySet().toArray(referers); 99 } 100 referersLen = -1; 101 } 102 103 104 /** 105 * @return the id of this thing as hex string 106 */ 107 public String getIdString() { 108 return Misc.toHex(getId()); 109 } 110 111 public String toString() { 112 return getClazz().getName() + "@" + getIdString(); 113 } 114 115 /** 116 * @return the StackTrace of the point of allocation of this object, 117 * or null if unknown 118 */ 119 public StackTrace getAllocatedFrom() { 120 return getClazz().getSiteTrace(this); 121 } 122 123 public boolean isNew() { 124 return getClazz().isNew(this); 125 } 126 127 void setNew(boolean flag) { 128 getClazz().setNew(this, flag); 129 } 130 131 /** 132 * Tell the visitor about all of the objects we refer to 133 */ 134 public void visitReferencedObjects(JavaHeapObjectVisitor v) { 135 v.visit(getClazz()); 136 } 137 138 void addReferenceFrom(JavaHeapObject other) { 139 if (referersLen == 0) { 140 referers = new JavaThing[1]; // It was null 141 } else if (referersLen == referers.length) { 142 JavaThing[] copy = new JavaThing[(3 * (referersLen + 1)) / 2]; 143 System.arraycopy(referers, 0, copy, 0, referersLen); 144 referers = copy; 145 } 146 referers[referersLen++] = other; 147 // We just append to referers here. Measurements have shown that 148 // around 10% to 30% are duplicates, so it's better to just append 149 // blindly and screen out all the duplicates at once. 150 } 151 152 void addReferenceFromRoot(Root r) { 153 getClazz().addReferenceFromRoot(r, this); 154 } 155 156 /** 157 * If the rootset includes this object, return a Root describing one 158 * of the reasons why. 159 */ 160 public Root getRoot() { 161 return getClazz().getRoot(this); 162 } 163 164 /** 165 * Tell who refers to us. 166 * 167 * @return an Enumeration of JavaHeapObject instances 168 */ 169 public Enumeration<JavaThing> getReferers() { 170 if (referersLen != -1) { 171 throw new RuntimeException("not resolved: " + getIdString()); 172 } 173 return new Enumeration<JavaThing>() { 174 175 private int num = 0; 176 177 public boolean hasMoreElements() { 178 return referers != null && num < referers.length; 179 } 180 181 public JavaThing nextElement() { 182 return referers[num++]; 183 } 184 }; 185 } 186 187 /** 188 * Given other, which the caller promises is in referers, determines if 189 * the reference is only a weak reference. 190 */ 191 public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) { 192 return false; 193 } 194 195 /** 196 * Describe the reference that this thing has to target. This will only 197 * be called if target is in the array returned by getChildrenForRootset. 198 */ 199 public String describeReferenceTo(JavaThing target, Snapshot ss) { 200 return "??"; 201 } 202 203 public boolean isHeapAllocated() { 204 return true; 205 } 206 207} 208