001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.heap;
042:
043: import java.util.ArrayList;
044: import java.util.Collection;
045: import java.util.HashMap;
046: import java.util.Iterator;
047: import java.util.List;
048: import java.util.Map;
049:
050: /**
051: *
052: * @author Tomas Hurka
053: */
054: class ClassDump extends HprofObject implements JavaClass {
055: //~ Instance fields ----------------------------------------------------------------------------------------------------------
056:
057: final ClassDumpSegment classDumpSegment;
058: private int instances;
059: private long loadClassOffset;
060:
061: //~ Constructors -------------------------------------------------------------------------------------------------------------
062:
063: ClassDump(ClassDumpSegment segment, long offset) {
064: super (offset);
065: classDumpSegment = segment;
066: assert getHprofBuffer().get(offset) == HprofHeap.CLASS_DUMP;
067: }
068:
069: //~ Methods ------------------------------------------------------------------------------------------------------------------
070:
071: public int getAllInstancesSize() {
072: if (isArray()) {
073: return ((Integer) classDumpSegment.arrayMap.get(this ))
074: .intValue();
075: }
076:
077: return getInstancesCount() * getInstanceSize();
078: }
079:
080: public boolean isArray() {
081: return classDumpSegment.arrayMap.get(this ) != null;
082: }
083:
084: public Instance getClassLoader() {
085: long loaderId = getHprofBuffer().getID(
086: fileOffset + classDumpSegment.classLoaderIDOffset);
087:
088: return getHprof().getInstanceByID(loaderId);
089: }
090:
091: public Field getField(String name) {
092: Iterator fIt = getFields().iterator();
093:
094: while (fIt.hasNext()) {
095: Field field = (Field) fIt.next();
096:
097: if (field.getName().equals(name)) {
098: return field;
099: }
100: }
101:
102: return null;
103: }
104:
105: public List /*<Field>*/getFields() {
106: HprofByteBuffer buffer = getHprofBuffer();
107: long offset = fileOffset + getInstanceFieldOffset();
108: int i;
109: int fields = buffer.getShort(offset);
110: List filedsList = new ArrayList(fields);
111:
112: for (i = 0; i < fields; i++) {
113: filedsList.add(new HprofField(this , offset + 2
114: + (i * classDumpSegment.fieldSize)));
115: }
116:
117: return filedsList;
118: }
119:
120: public int getInstanceSize() {
121: if (isArray()) {
122: return -1;
123: }
124:
125: return classDumpSegment.getMinimumInstanceSize()
126: + getHprofBuffer().getInt(
127: fileOffset
128: + classDumpSegment.instanceSizeOffset);
129: }
130:
131: public List /*<Instance>*/getInstances() {
132: return getHprof().computeInstances(this );
133: }
134:
135: public int getInstancesCount() {
136: if (instances == 0) {
137: getHprof().computeInstances();
138: }
139:
140: return instances;
141: }
142:
143: public long getJavaClassId() {
144: return getHprofBuffer().getID(
145: fileOffset + classDumpSegment.classIDOffset);
146: }
147:
148: public String getName() {
149: return getLoadClass().getName();
150: }
151:
152: public List /*<FieldValue>*/getStaticFieldValues() {
153: HprofByteBuffer buffer = getHprofBuffer();
154: long offset = fileOffset + getStaticFieldOffset();
155: int i;
156: int fields;
157: List filedsList;
158: HprofHeap heap = getHprof();
159:
160: fields = buffer.getShort(offset);
161: offset += 2;
162: filedsList = new ArrayList(fields);
163:
164: for (i = 0; i < fields; i++) {
165: byte type = buffer.get(offset
166: + classDumpSegment.fieldTypeOffset);
167: int fieldSize = classDumpSegment.fieldSize
168: + heap.getValueSize(type);
169: HprofFieldValue value;
170:
171: if (type == HprofHeap.OBJECT) {
172: value = new HprofFieldObjectValue(this , offset);
173: } else {
174: value = new HprofFieldValue(this , offset);
175: }
176:
177: filedsList.add(value);
178: offset += fieldSize;
179: }
180:
181: return filedsList;
182: }
183:
184: public Collection /*<JavaClass>*/getSubClasses() {
185: List classes = classDumpSegment.hprofHeap.getAllClasses();
186: List subclasses = new ArrayList(classes.size() / 10);
187: Map subclassesMap = new HashMap((classes.size() * 4) / 3);
188:
189: subclassesMap.put(this , Boolean.TRUE);
190:
191: for (int i = 0; i < classes.size(); i++) {
192: JavaClass jcls = (JavaClass) classes.get(i);
193: Boolean b = (Boolean) subclassesMap.get(jcls);
194:
195: if (b == null) {
196: b = isSubClass(jcls, subclassesMap);
197: }
198:
199: if ((b == Boolean.TRUE) && (jcls != this )) {
200: subclasses.add(jcls);
201: }
202: }
203:
204: return subclasses;
205: }
206:
207: public JavaClass getSuperClass() {
208: long super ClassId = getHprofBuffer().getID(
209: fileOffset + classDumpSegment.super ClassIDOffset);
210:
211: return classDumpSegment.getClassDumpByID(super ClassId);
212: }
213:
214: public Object getValueOfStaticField(String name) {
215: Iterator fIt = getStaticFieldValues().iterator();
216:
217: while (fIt.hasNext()) {
218: FieldValue fieldValue = (FieldValue) fIt.next();
219:
220: if (fieldValue.getField().getName().equals(name)) {
221: if (fieldValue instanceof HprofFieldObjectValue) {
222: return ((HprofFieldObjectValue) fieldValue)
223: .getInstance();
224: } else {
225: return ((HprofFieldValue) fieldValue)
226: .getTypeValue();
227: }
228: }
229: }
230:
231: return null;
232: }
233:
234: List getAllInstanceFields() {
235: List fields = new ArrayList(50);
236:
237: for (JavaClass jcls = this ; jcls != null; jcls = jcls
238: .getSuperClass()) {
239: fields.addAll(jcls.getFields());
240: }
241:
242: return fields;
243: }
244:
245: void setClassLoadOffset(long offset) {
246: loadClassOffset = offset;
247: }
248:
249: int getConstantPoolSize() {
250: long cpOffset = fileOffset
251: + classDumpSegment.constantPoolSizeOffset;
252: HprofByteBuffer buffer = getHprofBuffer();
253: int cpRecords = buffer.getShort(cpOffset);
254: HprofHeap heap = getHprof();
255:
256: cpOffset += 2;
257:
258: for (int i = 0; i < cpRecords; i++) {
259: byte type = buffer.get(cpOffset + 2);
260: int size = heap.getValueSize(type);
261: cpOffset += (2 + 1 + size);
262: }
263:
264: return (int) (cpOffset - (fileOffset + classDumpSegment.constantPoolSizeOffset));
265: }
266:
267: HprofHeap getHprof() {
268: return classDumpSegment.hprofHeap;
269: }
270:
271: HprofByteBuffer getHprofBuffer() {
272: return classDumpSegment.hprofHeap.dumpBuffer;
273: }
274:
275: int getInstanceFieldOffset() {
276: int staticFieldOffset = getStaticFieldOffset();
277:
278: return staticFieldOffset
279: + getStaticFiledSize(staticFieldOffset);
280: }
281:
282: LoadClass getLoadClass() {
283: return new LoadClass(getHprof().getLoadClassSegment(),
284: loadClassOffset);
285: }
286:
287: List getReferences() {
288: HprofByteBuffer buffer = getHprofBuffer();
289: byte[] idArr = new byte[buffer.getIDSize()];
290:
291: buffer.get(fileOffset + 1, idArr);
292:
293: return getHprof().findReferencesFor(getJavaClassId(), idArr);
294: }
295:
296: int getStaticFieldOffset() {
297: return classDumpSegment.constantPoolSizeOffset
298: + getConstantPoolSize();
299: }
300:
301: int getStaticFiledSize(int staticFieldOffset) {
302: int i;
303: HprofByteBuffer buffer = getHprofBuffer();
304: int idSize = buffer.getIDSize();
305: long fieldOffset = fileOffset + staticFieldOffset;
306: int fields = getHprofBuffer().getShort(fieldOffset);
307: HprofHeap heap = getHprof();
308:
309: fieldOffset += 2;
310:
311: for (i = 0; i < fields; i++) {
312: byte type = buffer.get(fieldOffset + idSize);
313: int size = heap.getValueSize(type);
314: fieldOffset += (idSize + 1 + size);
315: }
316:
317: return (int) (fieldOffset - staticFieldOffset - fileOffset);
318: }
319:
320: void findStaticReferencesFor(long instanceId, List refs) {
321: int i;
322: HprofByteBuffer buffer = getHprofBuffer();
323: int idSize = buffer.getIDSize();
324: long fieldOffset = fileOffset + getStaticFieldOffset();
325: int fields = getHprofBuffer().getShort(fieldOffset);
326: List staticFileds = null;
327: HprofHeap heap = getHprof();
328:
329: fieldOffset += 2;
330:
331: for (i = 0; i < fields; i++) {
332: byte type = buffer.get(fieldOffset + idSize);
333: int size = heap.getValueSize(type);
334:
335: if ((type == HprofHeap.OBJECT)
336: && (instanceId == buffer.getID(fieldOffset + idSize
337: + 1))) {
338: if (staticFileds == null) {
339: staticFileds = getStaticFieldValues();
340: }
341:
342: refs.add(staticFileds.get(i));
343: }
344:
345: fieldOffset += (idSize + 1 + size);
346: }
347: }
348:
349: void incrementInstance() {
350: instances++;
351: }
352:
353: private static Boolean isSubClass(JavaClass jcls, Map subclassesMap) {
354: JavaClass super Class = jcls.getSuperClass();
355: Boolean b;
356:
357: if (super Class == null) {
358: b = Boolean.FALSE;
359: } else {
360: b = (Boolean) subclassesMap.get(superClass);
361:
362: if (b == null) {
363: b = isSubClass(superClass, subclassesMap);
364: }
365: }
366:
367: subclassesMap.put(jcls, b);
368:
369: return b;
370: }
371: }
|