JavaHeapObject.java revision 2779:56d1e05e0def
191094Sdes/* 2115619Sdes * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3174832Sdes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 491094Sdes * 591094Sdes * This code is free software; you can redistribute it and/or modify it 691094Sdes * under the terms of the GNU General Public License version 2 only, as 799158Sdes * published by the Free Software Foundation. Oracle designates this 899158Sdes * particular file as subject to the "Classpath" exception as provided 999158Sdes * by Oracle in the LICENSE file that accompanied this code. 1091094Sdes * 1191094Sdes * This code is distributed in the hope that it will be useful, but WITHOUT 1291094Sdes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1391094Sdes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1491094Sdes * version 2 for more details (a copy is included in the LICENSE file that 1591094Sdes * accompanied this code). 1691094Sdes * 1791094Sdes * You should have received a copy of the GNU General Public License version 1891094Sdes * 2 along with this work; if not, write to the Free Software Foundation, 1991094Sdes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2091094Sdes * 2191094Sdes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2291094Sdes * or visit www.oracle.com if you need additional information or have any 2391094Sdes * questions. 2491094Sdes */ 2591094Sdes 2691094Sdes 2791094Sdes/* 2891094Sdes * The Original Code is HAT. The Initial Developer of the 2991094Sdes * Original Code is Bill Foote, with contributions from others 3091094Sdes * at JavaSoft/Sun. 3191094Sdes */ 3291094Sdes 3391094Sdespackage jdk.test.lib.hprof.model; 3491094Sdes 35174832Sdesimport java.util.Enumeration; 3691094Sdesimport java.util.HashMap; 3791094Sdesimport java.util.Map; 3891094Sdesimport jdk.test.lib.hprof.util.Misc; 3991094Sdes 4091094Sdes 4191094Sdes/** 4291094Sdes * 4391094Sdes * @author Bill Foote 4491094Sdes */ 45115619Sdes 46115619Sdes/** 4791094Sdes * Represents an object that's allocated out of the Java heap. It occupies 4891094Sdes * memory in the VM, and is the sort of thing that in a JDK 1.1 VM had 4991094Sdes * a handle. It can be a 5091094Sdes * JavaClass, a JavaObjectArray, a JavaValueArray or a JavaObject. 5191094Sdes */ 5291094Sdes 5391094Sdespublic abstract class JavaHeapObject extends JavaThing { 54174832Sdes 5591094Sdes // 5691094Sdes // Who we refer to. This is heavily optimized for space, because it's 5791094Sdes // well worth trading a bit of speed for less swapping. 5891094Sdes // referers and referersLen go through two phases: Building and 5991094Sdes // resolved. When building, referers might have duplicates, but can 6091094Sdes // be appended to. When resolved, referers has no duplicates or 6191094Sdes // empty slots. 6291094Sdes // 6391094Sdes private JavaThing[] referers = null; 6491094Sdes private int referersLen = 0; // -1 when resolved 65115619Sdes 6691094Sdes public abstract JavaClass getClazz(); 6791094Sdes public abstract long getSize(); 6891100Sdes public abstract long getId(); 6991100Sdes 7091100Sdes /** 7191100Sdes * Do any initialization this thing needs after its data is read in. 7291100Sdes * Subclasses that override this should call super.resolve(). 7391100Sdes */ 7491100Sdes public void resolve(Snapshot snapshot) { 7591100Sdes StackTrace trace = snapshot.getSiteTrace(this); 7691100Sdes if (trace != null) { 7791100Sdes trace.resolve(snapshot); 7891100Sdes } 7991100Sdes } 8091100Sdes 8191100Sdes // 8291100Sdes // Eliminate duplicates from referers, and size the array exactly. 8391100Sdes // This sets us up to answer queries. See the comments around the 8491100Sdes // referers data member for details. 8591100Sdes // 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